BetaThis is a live doc! Anyone with edit access can make updates in real time without having to publish.
By Bryan

本地转发

定义:访问本机的 6000 端口 = 访问本机的 5000 端口

socat

假设,需要将本地 6000 端口转到指定的 5000 端口,利用如下 socat 命令

1socat TCP-LISTEN:6000,fork TCP:127.0.0.1:5000

netcat (nc)

假设,需要将本地 6000 端口转到指定的 5000 端口,利用如下 nc 命令

1nc -l -k -p 6000 -c "nc 127.0.0.1 5000" 2 3# 某些版本 -k 不生效。。 4# 可以强制用 5# while true; do nc -l -k -p 6000 -c "nc 127.0.0.1 5000"; done

iptables

首先需要先开启内核流量转发功能

1modprobe br_netfilter 2echo 1 > /proc/sys/net/ipv4/ip_forward

假设,需要将本地 6000 端口转到指定的 5000 端口,利用如下 iptables 命令

1# 转发外来流量 2# 172.16.0.2 为连接外网的网卡 ip 3# 192.168.0.2 为转发的目标 ip 4iptables -t nat -A PREROUTING \ 5 -d 172.16.0.2 -p tcp -m tcp --dport 6000 \ 6 -j DNAT --to-destination 192.168.0.2:5000 7 8# 转发本地流量(本地流量不会走 PREROUTING 链) 9# 127.0.0.1 为本地的 ip 地址(也可以使用 127.0.0.1/8 这种 CIDR) 10iptables -t nat -A OUTPUT \ 11 -d 127.0.0.1 -p tcp -m tcp --dport 6000 \ 12 -j DNAT --to-destination 192.16 13 8.0.2:5000

远程转发

定义:

  1. 访问本机的 6000 端口 = 访问另一台机器的 5000 端口

  2. 访问另一台机器的 6000 端口 = 访问本机的 5000 端口

访问本地端口 → 访问另一台机器的端口

1ssh -L 6000:127.0.0.1:5000 remoteuser@remoteip

称为「SSH 本地转发」,利用 -L 开启

命令执行时不是「单纯转发端口」,而也会连接 shell,如果不想可以加上 -N 参数

完整的用法是

  • -L [bind_address:]port:host:hostport

  • -L [bind_address:]port:remote_socket

  • -L local_socket:host:hostport

  • -L local_socket:remote_socket

  • 不仅仅是端口转发,还可以支持本地或远程的 unix socket 文件

  • 不仅仅是访问远程端口,还可以通过远程机器做跳板机访问到其他机器的网络

    • 例如 ssh -L 6000:2.2.2.2:5000 1.1.1.1,则访问本机 localhost:6000 时,实际上是用 1.1.1.1 机器访问的 2.2.2.2:5000

  • 不仅仅绑定到本地的 localhost,还可以通过指定 bind_address 绑定到 0.0.0.0 或其他 IP

    • 如果需要绑定其他 IP,需要本地 ssh_config 设置 GatewayPorts 为 true,或增加 -g 参数

访问远程端口 → 访问本机的端口

1ssh -R 5000:127.0.0.1:6000 remoteuser@remoteip

称为「SSH 远程转发」,利用 -R 开启

同样的,命令执行时不是「单纯转发端口」,而也会连接 shell,如果不想可以加上 -N 参数

因为这个命令会在远程机器上暴露端口,因此需要修改远程 sshd 的配置

  • AllowTcpForwarding 需要修改为 yes(默认为 true)

  • 如果想要让目标机器使用 localhost 以外的网卡,需要设置 GatewayPorts 为 true

同时需要对应端口未被占用、使用的账号有权利使用特定端口(例如只有 root 用户可以监听 < 1024 的端口)

完整的用法是

  • -R [bind_address:]port:host:hostport

  • -R [bind_address:]port:local_socket

  • -R remote_socket:host:hostport

  • -R remote_socket:local_socket

  • -R [bind_address:]port

  • 不仅仅是端口转发,还可以支持本地或远程的 unix socket 文件

  • 可以自由选择将本地的端口映射到远程的哪个 interface

    • 但是想映射到 localhost 以外的,需要远端配置 GatewayPorts 为 true

  • 可以将远程 port 指定为 0,这时远程服务器会自动寻找一个可用端口

    • 搭配 -O forward 以打印远程分配的端口

动态转发

1ssh -D 5000 remoteuser@remoteip

在本地指定端口启用一个 socks5 代理,通过这个代理可访问到目标机器

完整的用法是 -D [bind_address:]port

  • 不仅仅绑定到本地的 localhost,还可以通过指定 bind_address 绑定到 0.0.0.0 或其他 IP

    • 如果需要绑定其他 IP,需要本地 ssh_config 设置 GatewayPorts 为 true,或增加 -g 参数

参考

https://man7.org/linux/man-pages/man1/ssh.1.html

https://lotabout.me/2019/SSH-Port-Forwarding/

https://ednovas.xyz/2021/12/05/linuxforward/