端口转发,也称为端口映射,是一种允许远程设备连接到您的私有局域网(LAN)内特定服务的方法。顾名思义,该过程涉及将针对特定端口的请求转发到另一个端口或网络。它在传输过程中修改数据包的目的地,被认为是一种网络地址转换(NAT)操作。
启用端口转发允许那些未连接到内部网络的设备或主机相互访问,否则在禁用时会受到限制。您可以利用端口转发的优势来阻止目标网站、提升安全性,并根据需要绕过 NAT 防火墙。
在本教程中,我们将引导您完成在 Linux 中使用 iptables 进行端口转发的步骤。
前提条件
要学习本教程,您需要:
- 安装 Ubuntu在您的系统上。
- 在同一数据中心内的两台 Ubuntu 20.04 主机,且启用了私有网络.
- 设置了具有 sudo 特权的非 root 用户帐户在每台机器上。
主机详情
首先,我们需要了解工作服务器的接口和地址详情。让我们检查系统的网络接口:
|
1 |
ip -4 addr show scope global |
您将看到以下输出:
|
1 2 3 4 5 6 7 8 9 |
示例输出 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 198.51.100.45/18 brd 45.55.191.255 scope global eth0 valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 192.168.1.5/16 brd 10.132.255.255 scope global eth1 valid_lft forever preferred_lft forever |
在这里,高亮的输出显示了两个接口,第一个是 eth0 分配给地址 192.51.100.45,第二个是 eth1 分配给地址 192.168.1.5。在这两个接口中,一个是公网接口,另一个是私网接口。我们将运行一个命令来区分这两者,并找出连接到默认网关的公网接口。要进行区分,请输入:
|
1 |
ip route show | grep default= |
您将看到以下输出:
|
1 2 3 |
输出: ip route show | grep default |
本教程的虚拟数据
在本教程中,我们将使用虚拟地址和接口分配。您可以根据需要自由使用这些数据或替换它们。
Web 服务器网络详情:
-
公网 IP 地址: 203.0.113.2
-
私网 IP 地址: 192.0.2.2
-
公网接口: eth0
-
私网接口: eth1
防火墙网络详情:
-
公网 IP 地址: 203.0.113.15
-
私网 IP 地址: 192.0.2.15
-
公网接口: eth0
-
私网接口: eth1
Web 服务器设置
让我们从 Web 服务器主机开始。首先,使用您的 sudo 用户登录。
安装 Nginx
首先,我们将安装 Nginx在我们的 Web 服务器主机上,并对其进行限制,使其仅监听其私网接口。这将确保只有在我们以正确的方式设置了端口转发时,我们的 Web 服务器才可用。
接下来,更新本地软件包缓存并使用 apt 下载并安装 Nginx:
|
1 |
sudo apt-get update |
|
1 |
sudo apt-get install nginx |
添加限制
在 Web 服务器主机上安装 Nginx 后,我们将对其进行锁定,以确保它仅接受来自私网接口的输入,而不接受其他任何地方的输入。此外,它将确保只有在端口转发设置正确的情况下,我们的 Web 服务器才会处于活动状态。
要添加限制,请打开默认的服务器块配置文件 /etc/nginx/sites-enabled/default 在您选择的任何文本编辑器上(这里我们使用的是 nano 文本编辑器),然后输入:
|
1 |
sudo nano /etc/nginx/sites-enabled/default |
在输出中,您将看到 listen 指令出现两次:

在本教程中,我们使用第一个指令来演示 IPv4 转发。第二个针对 IPv6 配置的指令可以删除。在 80 前面加上冒号和您 Web 服务器的私有 IP 地址,以通知 Nginx 仅从私有接口接收输入。接下来,编辑该指令:

完成后,保存并关闭文件。在继续之前,请确保没有语法错误。让我们测试一下该文件:
|
1 |
sudo nginx -t |

如果您没有看到显示任何错误,就可以重启 Nginx 并启用新配置了:
|
1 |
sudo service nginx restart |
网络限制验证
让我们验证一下我们对 Web 服务器的访问级别。尝试使用私有接口并利用 curl 命令:
|
1 |
curl --connect-timeout 5 192.0.2.2 |
您将看到输出:

如果我们尝试使用公共接口,我们将无法连接:
|
1 |
curl --connect-timeout 5 203.0.113.2 |
|
1 |
curl: (7) Failed to connect to 203.0.113.2 port 80: Connection refused |
这正是我们所期望的。
配置防火墙以转发 80 端口
让我们继续在防火墙机器上实现端口转发的工作。
在内核中启用转发
默认情况下,大多数系统的端口转发都是关闭的。我们将通过进行一些编辑来开启端口转发。此外,还可以选择使用 sudo 权限永久开启端口转发,如接下来的步骤所示。
要在内核级别开启流量转发,请输入:
|
1 |
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward |
要永久开启端口转发,请编辑 /etc/sysctl.conf 文件。使用 sudo 权限打开该文件,然后输入:
|
1 |
sudo nano /etc/sysctl.conf |
在文件内部,找到并取消注释如下所示的行:
|
1 |
net.ipv4.ip_forward=1 |
完成后,保存并关闭文件。然后,使用 sysctl 命令应用设置中的更改以使其生效:
|
1 |
sudo sysctl -p |
|
1 |
sudo sysctl --system |
基础防火墙设置
首先,阅读关于如何在您的机器上设置基础防火墙的指南。完成后,您将拥有:
- 已安装 iptables-persistent
- 已将默认规则集保存到 /etc/iptables/rules.v4
- 关于使用 iptables 命令添加和修改规则的全面知识
此外,您还可以查看如何列出和删除 iptables 防火墙规则.
添加转发规则
我们将配置防火墙,以确保流入我们公共接口( eth0 )上端口 80 的流量被转发到我们的私有接口( eth1)。默认情况下,我们的基础防火墙将 FORWARD 链设置为 DROP 流量。添加防火墙规则将允许转发连接到我们的 Web 服务器。为了增加安全性,我们将锁定防火墙规则以允许转发请求。
在 FORWARD 链中,我们将接受目的地为端口 80 、来自我们公共接口并流向我们私有接口的新连接。我们将借助 conntrack 扩展来识别新连接,并用 TCP SYN 数据包来表示它们:
|
1 |
sudo iptables -A FORWARD -i eth0 -o eth1 -p tcp --syn --dport 80 -m conntrack --ctstate NEW -j ACCEPT |
您需要允许由传入连接产生的双向后续流量。输入以下命令以允许 ESTABLISHED 和 RELATED 我们公共和私有接口之间的流量:
|
1 |
iptables -A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT |
|
1 |
iptables -A FORWARD -i eth1 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT |
让我们验证我们在 FORWARD 链上的策略是否已设置为 DROP:
|
1 |
sudo iptables -P FORWARD DROP |
到目前为止,我们已经添加了一些规则,允许公共接口和私有接口之间的流量通过我们的防火墙。然而, iptables 尚未收到引导流量的通知,因为防火墙规则配置尚未完成。在接下来的步骤中,我们将添加 NAT 规则并调整永久规则集以引导流量。
添加 NAT 规则以引导数据包
我们将执行两个独立的操作,以便 iptables 能够正确修改数据包,并简化与客户端和 Web 服务器的通信。
DNAT 是启动 PREROUTING 链的第一个操作,该链属于 nat 表。该操作会修改数据包的目的地址,使其在网络间传输时能够被正确路由。然而,公共网络上的客户端将连接到我们的防火墙服务器,并且不了解我们私有网络的拓扑结构。为了与私有网络传递信息,需要更改每个数据包的目的地址,使其能够正确到达我们的目的 Web 服务器。
需要特别注意的是,我们专注于配置端口转发。对到达防火墙的每个数据包都执行 NAT 并不在本教程的讨论范围内。我们将匹配端口 80 并将其映射到我们 Web 服务器的私有 IP 地址:
|
1 |
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.0.2.2 |
数据包将被正确路由到我们的 Web 服务器,其中包含客户端的原始地址作为源地址。尽管服务器尝试直接向该地址发送回复,但将无法建立合法的 TCP 连接。
为了配置正确的路由,我们将修改数据包的源地址。让我们将源地址修改为我们防火墙服务器的私有 IP 地址。修改后,回复将被发送回防火墙,然后再由防火墙转发回客户端。
要启用此功能,请在 POSTROUTING 链中添加一条规则,该链属于 nat 表,并在数据包发送到网络之前对其进行评估。然后,通过 IP 地址和端口匹配发往我们 Web 服务器的数据包:
|
1 |
sudo iptables -t nat -A POSTROUTING -o eth1 -p tcp --dport 80 -d 192.0.2.2 -j SNAT --to-source 192.0.2.15 |
此规则生效后,通过将我们的网页浏览器指向防火墙机器的公共地址,应该就可以访问我们的 Web 服务器:
|
1 |
curl 203.0.113.15 |
您将看到以下输出:

我们的端口转发设置已完成。
调整永久规则集
完成端口转发设置后,我们将此保存到我们的永久规则集中。如果您想保留当前规则集中的注释,请使用 iptables-persistent 服务来保存您的规则:
|
1 |
sudo service iptables-persistent save |
您也可以打开它并手动编辑,以保留文件中的注释:
|
1 |
sudo nano /etc/iptables/rules.v4 |
接下来,配置 filter 表和 nat 表,以分别添加 FORWARD 链规则和 ROUTING 规则。调整 nat 表将允许我们添加 PREROUTING 和 POSTROUTING 规则,如下例所示:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
/etc/iptables/规则.v4 *过滤 # 默认允许所有传出,但丢弃传入和转发数据包 :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [0:0] # 自定义每个协议的链 :UDP - [0:0] :TCP - [0:0] :ICMP - [0:0] # 可接受的 UDP 流量 # 可接受的 TCP 流量 -A TCP -p tcp --dport 22 -j ACCEPT # 可接受的 ICMP 流量 # 样板接受策略 -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT -A INPUT -i lo -j ACCEPT # 丢弃无效数据包 -A INPUT -m conntrack --ctstate INVALID -j DROP # 将流量传递到特定协议的链 ## 仅允许新连接(已建立和相关的连接应该已经处理) ## 对于 TCP,另外仅允许新的 SYN 数据包,因为这是建立新 TCP 连接的唯一有效 ## 方法 -A INPUT -p udp -m conntrack --ctstate NEW -j UDP -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP -A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP # 拒绝所有落到此处的包 ## 尝试使用特定于协议的拒绝消息 -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable -A INPUT -p tcp -j REJECT --reject-with tcp-reset -A INPUT -j REJECT --reject-with icmp-proto-unreachable # 将端口 80 转发到我们的 Web 服务器的规则 # Web 服务器网络详情: # * 公网 IP 地址:203.0.113.2 # * 私网 IP 地址:192.0.2.2 # * 公网接口:eth0 # * 私网接口:eth1 # # 防火墙网络详情: # # * 公网 IP 地址:203.0.113.15 # * 私网 IP 地址:192.0.2.15 # * 公网接口:eth0 # * 私网接口:eth1 -A FORWARD -i eth0 -o eth1 -p tcp --syn --dport 80 -m conntrack --ctstate NEW -j ACCEPT -A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT -A FORWARD -i eth1 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # 转发过滤规则结束 # 提交更改 COMMIT *raw :PREROUTING ACCEPT [0:0] :OUTPUT ACCEPT [0:0] COMMIT *nat :PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] # 转换对公网接口 80 端口请求的规则 # 以便我们可以使用 # 私网接口正确转发到 Web 服务器。 # Web 服务器网络详情: # * 公网 IP 地址:203.0.113.2 # * 私网 IP 地址:192.0.2.2 # * 公网接口:eth0 # * 私网接口:eth1 # # 防火墙网络详情: # # * 公网 IP 地址:203.0.113.15 # * 私网 IP 地址:192.0.2.15 # * 公网接口:eth0 # * 私网接口:eth1 -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.0.2.2 -A POSTROUTING -d 192.0.2.2 -o eth1 -p tcp --dport 80 -j SNAT --to-source 192.0.2.15 # Web 服务器流量的 NAT 转换结束 COMMIT *security :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] COMMIT *mangle :PREROUTING ACCEPT [0:0] :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] COMMIT |
添加上述值后,保存并关闭文件。接下来,输入以下命令来测试规则的语法:
|
1 |
sudo iptables-restore -t < /etc/iptables/rules.v4 |
如果未看到任何错误,请加载规则集:
|
1 |
sudo service iptables-persistent reload |
让我们验证一下,是否仍可以通过防火墙的公网 IP 地址访问我们的 Web 服务器:
|
1 |
curl 203.0.113.15 |
结论
在本教程结束时,您应该已经能够熟练地在 Linux 服务器上使用 iptables 进行端口转发。您可以利用端口转发功能来隐藏私有网络’的拓扑结构,同时使服务流量能够顺畅地通过网关防火墙机器。
由于该过程明确依赖于您的网络安全和所使用的端口,因此它是安全的。如果您的网络上没有安全防火墙或 VPN 安全保护,则可能会存在风险。因此,建议按照本教程中的讨论配置防火墙。我们希望本指南能帮助您在使用私有网络时在互联网上保持安全。
要进一步探索可在系统上实施的更多防火墙解决方案,请查看来自 我们的博客:
祝您使用愉快!
评论
暂无评论。发表第一条评论吧。