使用iptables实现端口转发
SSH 也能实现本机的端口转发,只不过原来的 1 条连接会变成 3 条。而 iptables 的端口转发则是在内核进行(netstat是看不到的),效率相对更高。下面介绍其典型的几种端口转发形式。
将本地的端口转发到本机端口
设置端口转发
将本机的 7777 端口转发到 6666 端口(该设置方式在机器重启之后失效):
1 | root@host01$ iptables -t nat -A PREROUTING -p tcp --dport 7777 -j REDIRECT --to-port 6666 |
在本机侦听 6666 端口:
1 | root@host01$ nc -lk 6666 |
在 host02 上连接 host01 的 7777 端口,虽然host01的 7777 端口并未被侦听,但是被转发给了处于侦听状态的 6666 端口:
1 | root@host02$ nc host01 7777 |
在 host02 上查看连接信息(ping host01 得到其IP 192.168.56.104):
在 host01 上查看连接信息(ping host02 得到其IP 192.168.56.105)
注意:在host02上看到的连接端口是7777,而在host01上看到的连接端口是6666。
查看端口转发
查看当前iptables 的 nat 表的所有规则:(不用 -t 指定表名默认的是指 filter 表)
1 | iptables -t nat -nL --line |
删除指定表指定链上的规则
删除指定表的指定链上的规则, -D 并指定序号即可。
1 | iptables -t nat -D PREROUTING 1 |
注:PREROUTING链修改的是从外部连接过来时的转发,如果本机连接到本机的转发【只能是在本机内部转发】,需要对 OUTPUT 链做操作。
1 | iptables -t nat -A OUTPUT -p tcp --dport 7777 -j REDIRECT --to-port 6666 |
将本机的端口转发到其他机器
设置端口转发
通过 host01【104】 的 6666 端口访问 host02【105】 的 7777 端口,在 host01 上设置:
1 | # 这里只能通过 IP 进行设置,并且 net.ipv4.ip_forward=1 必须设置后才能生效 |
实验验证
可以看到 host01【104】 收到的包被转发。因为转发发生在内核,在转发机上,使用 ss 看不到任何与 host02【105】 和 host03【106】 的连接。
延伸实现SSH跳板机
从上面可以看出,我们只要把 host02【105】 的 7777端口改成22端口,就可以实现用 host01【104】做跳板机登录的目的。
将一台公网 ip 主机的端口转发到另一台公网 ip 主机
我有两台AWS主机,一台位于伦敦,一台位于纽约。红色为对应主机的公网 ip,黑色为私网ip。 将伦敦主机的 8000 端口转发到纽约的 9000 端口。
在伦敦主机上操作:
1 | iptables -t nat -A PREROUTING -p tcp --dport 8000 -j DNAT --to-destination 128.113.255.255:9000 |
注意:这里关键的地方在于 SNAT 之后的 source 地址只能是内网地址,不能 London 主机的公网地址
。
如果配成了伦敦主机的公网地址,则转发不会成功。
虽然通过公网 ip 连接主机,但实际上在主机上抓包显示,数据包的目的地址都是主机的私网地址。DNAT 修改了数据包的目的地址,SNAT修改了数据包的源地址,一旦源地址被修改为本机的公网地址,该数据包将会被丢弃。