现象
之前使用socat、ssh tunnel 能在应用层做转发,这次想在netfilter里面就把转发做掉,但是犯了一个错误:在本台机器上面产生的包不通过nat的PREROUTING链。
测试命令(错误)
- 添加trace
sudo iptables -t raw -A PREROUTING -j TRACE -p tcp --dport 8003 --destination 127.0.0.1
这条命令可以追踪从lo这个接口进来的包。
- 添加DNAT
sudo iptables -t nat -A PREROUTING -j DNAT -p tcp --destination 127.0.0.1 --dport 8083 --to-destination 121.121.121.121
这条命令就是想把dst_addr改成121.121.121.121
- 在121.121.121.121远端机器上,用nc 起一个监听
nc -l 8083
- 在本地机器上curl
curl http://localhost:8083 --interface enp88s0
- 查看trace
看不到任何的关于PREROUTING链之后的步骤
红框里面的地方都没走到,看样子在本地发出的包,不会走INPUT PATH。
测试命令(正确)
- 在OUTPUT链里面加DNAT,在POSTROUTING链里面加MASQUERADE
sudo iptables -t nat -A OUTPUT -j DNAT -p tcp --dport 8083 --to-destination 121.121.121.121
sudo iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp --destination 121.121.121.121
- 可选项(在raw表OUTPUT里面添加TRACE)
从图里面可以看到从本地出来的包,首先会到raw的OUTPUT,所以可以在这里加一个TRACE
sudo iptables -t raw -A OUTPUT -j TRACE -p tcp --dport 8083
- curl
curl http://localhost:8083 --interface enp88s0
现在就能正确访问到121.121.121.121:8083端口了。
注意点
- 使用curl命令的时候,需要指定interface,要不然就默认使用lo这个接口发包,指定为interface的时候,trace可以看到:
可以看到日志里面的流程跟图上是对的上的。
但是使用lo这个接口来执行curl的时候,包就出不去了:
可以看到在filter OUTPUT这一步就没了,可能就把包丢掉了。但是在filter OUTPUT里面没看到相关的DROP规则,包到哪里去了还要进一步研究下。
相关链接
Unable to get NAT working via iptables PREROUTING chain