首先要开启转发功能

vi /etc/sysctl.conf 
net.ipv4.ip_forward = 1
sysctl -p

iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j DNAT --to-destination 143.198.49.222:80
iptables -t nat -A PREROUTING -p udp -m udp --dport [本地端口] -j DNAT --to-destination [目的IP]:[目的端口]
iptables -t nat -A POSTROUTING -p tcp -m tcp -d 143.198.49.222 --dport 80 -j SNAT --to-source 192.168.0.117
iptables -t nat -A POSTROUTING -p udp -m udp -d [目的IP] --dport [目的端口] -j SNAT --to-source [本地IP]
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 443 -j DNAT --to-destination 143.198.49.222:443
iptables -t nat -A POSTROUTING -p tcp -m tcp -d 143.198.49.222 --dport 443 -j SNAT --to-source 192.168.0.117

其中

PREROUTING 预处理

--to-destination 修改目的

POSTROUTING 发送的时候

--to-source 修改源

在设置转发的时候如果要转发到内网/环回(127.0.0.1)则必须做如下配置

vi /etc/sysctl.conf
net.ipv4.conf.enp6s0f0.route_localnet = 1
sysctl -p

其中 enp6s0f0 是允许的网卡 有些机器可能是eth0

iptables -t nat -A PREROUTING -p tcp -m tcp --dport 22228 -j DNAT --to-destination 127.0.0.1:22228
iptables -t nat -A POSTROUTING -p tcp -m tcp -d 127.0.0.1 --dport 22228 -j SNAT --to-source 127.0.0.1

虽然可以转发到环回,但并不建议这么做,因为这样是不安全的,原因如下:

经典的《专家们公认的20个最危险的安全漏洞》一文中有下面的论述:

G5 – 没有过滤地址不正确的包

G5.1描述

IP地址欺诈是黑客经常用来隐藏自己踪迹的一种手段。例如常见的smurf攻击就利用了路由的特性向数以千记的机器发出了一串数据包。每一个数据包都假冒了一个受害主机的IP地址作为源地址,于是上千台主机会同时向这个受害的主机返回数据包,导致该主机或网络崩溃。对流进和流出你网络的数据进行过滤可以提供一种高层的保护。过滤规则如下:

1. 任何进入你网络的数据包不能把你网络内部的地址作为源地址。

2. 任何进入你网络的数据包必须把你网络内部的地址作为目的地址。

3. 任何离开你网络的数据包必须把你网络内部的地址作为源地址。

4. 任何离开你网络的数据包不能把你网络内部的地址作为目的地址。

5. 任何进入或离开你网络的数据包不能把一个私有地址(private address)或在RFC1918中 列出的属于保留空间(包括10.x.x.x/8, 172.16.x.x/12 或192.168.x.x/16 和网络回送地址 127.0.0.0/8.)的地址作为源或目的地址。

6. 阻塞任意源路由包或任何设置了IP选项的包。

可见,阻塞这种目标为环回地址的包是合理的,然而这件事到底应该有谁来做,这是一个问题,到底应该由防火墙软件来做呢,还是操作系统协议栈本身来做?Linux是在IP路由模块中做的,我认为这样不是很合理,有时候我真的需要这个功能,总不能重新编译一下内核吧,我觉得要么做到Netfilter中,要么就像rp_filter那样,做成可以配置的开关。