如何使用 Iptables 通过 Linux 网关转发端口

介绍

NAT,或网络地址翻译,是用来将数据包转移到替代地址的通用术语,通常用于允许流量超越网络界限。

_Port forwarding 是将特定端口请求转发到另一个主机、网络或端口的过程,由于此过程改变了飞行中包的目的地,因此被认为是一种NAT操作。

在本教程中,我们将展示如何使用iptables来通过NAT技术将端口转发到防火墙背后的主机。

前提条件

要跟随这个指南,你将需要:

  • 在同一数据中心设置两个Ubuntu 20.04服务器,并启用私人网络。 在每台机器上,你都需要设置一个非root 用户账户,并有`sudo'权限。 您可以在 [Ubuntu 20.04 初始服务器设置指南] (https://andsky.com/tech/tutorials/initial-server-setup-with-ubuntu-20-04 ) 上学习如何使用我们的指南来做到这一点。 确保跳过此指南的 ** 第 4 段 ** , 因为我们将在此教程中设置和配置防火墙 。
  • 联合国 在 ** 您的服务器中 ** 设置一个带有 iptables 的防火墙模板, 以便它能作为您的防火墙服务器运行 。 您可以遵循我们关于如何在Ubuntu 200.04(https://andsky.com/tech/tutorials/how-to-implement-a-basic-firewall-template-with-iptables-on-ubuntu-20-04)上安装可通性的基本防火墙的指南来做到这一点。 完成后, 您的防火墙服务器应具备下列条件可供使用 :
  • 安装了表-持久性
  • 将默认规则保存为`/etc/iptables/rules.v4'
  • 了解如何通过编辑规则文件或使用`表格 ' 命令来增加或调整规则

您设置防火墙模板的服务器将作为您的私人网络的防火墙和路由器。 为示范目的,第二台主机将配置为仅通过其私人接口访问的Web服务器。

主持人 详情

在您开始之前,您需要知道您的两个服务器正在使用哪些接口和地址。

查找您的网络细节

要了解您自己的系统的细节,请从搜索您的网络接口开始,您可以通过执行以下操作来找到您的机器上的接口和与它们相关的地址:

1ip -4 addr show scope global
1[secondary_label Sample Output]
22: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
3    inet 203.0.113.1/18 brd 45.55.191.255 scope global eth0
4       valid_lft forever preferred_lft forever
53: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
6    inet 10.0.0.1/16 brd 10.132.255.255 scope global eth1
7       valid_lft forever preferred_lft forever

突出输出显示两个接口(‘eth0’和‘eth1’)和每个接口分配的地址(分别为‘203.0.113.1’和‘10.0.0.1’)。

1ip route show | grep default
1[secondary_label Output]
2default via 111.111.111.111 dev eth0

来自此输出的界面信息(在本示例中‘eth0’)将是连接到默认网关的界面。

在您的每台机器上找到这些值,并使用它们跟随本指南的其余部分。

本指南中使用的样本数据

为了让事情更加清晰,我们将在本教程中使用以下空地址和界面分配。

网络服务器细节:

  • 公共 IP 地址: 203.0.113.1 * 私人 IP 地址: 10.0.0.1 * 公共接口: eth0 * 私人接口: eth1

网络防火墙细节:

  • 公共 IP 地址: 203.0.113.2 * 私人 IP 地址: 10.0.0.2 * 公共接口: eth0 * 私人接口: eth1

设置 Web 服务器

开始连接到您的Web服务器主机,并与您的sudo用户登录。

安装 Nginx

第一步是将 Nginx 安装在您的 Web 服务器主机上,并锁定它,以便它只倾听其私人接口,这将确保您的 Web 服务器只有当您正确设置端口转发时才可用。

首先,更新本地包缓存:

1[environment second]
2sudo apt update

接下来,使用apt来下载和安装软件:

1[environment second]
2sudo apt install nginx

限制 Nginx 到私人网络

在 Nginx 安装后,打开默认服务器封锁配置文件,以确保它只收听私人接口。

1[environment second]
2sudo nano /etc/nginx/sites-enabled/default

内部,找到倾听指令. 它应该列出两次连接到配置的顶部:

1[label /etc/nginx/sites-enabled/default]
2[environment second]
3server {
4    listen 80 default_server;
5    listen [::]:80 default_server ipv6only=on;
6
7    . . .
8}

在第一个倾听指令中,在80之前添加您的 Web 服务器的私人 IP 地址和一个字符串,以告知 Nginx 只能在私人接口上倾听。

接下来,修改倾听指令如下:

1[label /etc/nginx/sites-enabled/default]
2[environment second]
3server {
4    listen 10.0.0.1:80 default_server;
5
6    . . .
7}

如果您使用了nano,您可以通过按CTRL + X,然后按YENTER来做到这一点。

现在测试文件的语法错误:

1[environment second]
2sudo nginx -t
1[secondary_label Output]
2[environment second]
3nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
4nginx: configuration file /etc/nginx/nginx.conf test is successful

如果输出中没有错误,请重新启动 Nginx 以启用新配置:

1[environment second]
2sudo systemctl restart nginx

检查网络限制

在此时刻,有用的是验证您对您的 Web 服务器的访问水平。

从您的防火墙服务器,尝试使用以下命令从私人接口访问您的 Web 服务器:

1[environment third]
2curl --connect-timeout 5 10.0.0.1

如果成功,您的输出将导致以下消息:

 1[secondary_label Output]
 2[environment third]
 3<!DOCTYPE html>
 4<html>
 5<head>
 6<title>Welcome to nginx!</title>
 7<style>
 8    body {
 9        width: 35em;
10        margin: 0 auto;
11        font-family: Tahoma, Verdana, Arial, sans-serif;
12    }
13</style>
14</head>
15<body>
16<h1>Welcome to nginx!</h1>
17. . .

如果您尝试使用公共界面,您将收到一个消息,称它无法连接:

1[environment third]
2curl --connect-timeout 5 203.0.113.1
1[secondary_label Output]
2[environment third]
3curl: (7) Failed to connect to 203.0.113.1 port 80: Connection refused

这些结果预计。

设置防火墙向前端口 80

现在您将致力于在您的防火墙机器上实施端口转发 **。

在内核中允许传输

您需要做的第一件事是在内核级别启用流量转发. 默认情况下,大多数系统都关闭了转发。

若要只启用此会话的端口转发,请执行以下操作:

1[environment third]
2echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
1[secondary_label Output]
2[environment third]
31

要永久启用端口转发,您需要编辑 /etc/sysctl.conf 文件. 您可以通过打开具有 sudo 特权的文件来完成此操作:

1[environment third]
2sudo nano /etc/sysctl.conf

在檔案內,尋找並無評論如下所讀的行:

1[label /etc/sysctl.conf]
2[environment third]
3net.ipv4.ip_forward=1

保存并关闭文件,当你完成。

然后应用此文件中的设置. 首先运行以下命令:

1[environment third]
2sudo sysctl -p
1[secondary_label Output]
2[environment third]
3net.ipv4.ip_forward = 1

然后运行相同的命令,但将-p旗替换为 - 系统:

1[environment third]
2sudo sysctl --system
 1[secondary_label Output]
 2[environment third]
 3. . .
 4* Applying /usr/lib/sysctl.d/50-pid-max.conf ...
 5kernel.pid_max = 4194304
 6* Applying /etc/sysctl.d/99-cloudimg-ipv6.conf ...
 7net.ipv6.conf.all.use_tempaddr = 0
 8net.ipv6.conf.default.use_tempaddr = 0
 9* Applying /etc/sysctl.d/99-sysctl.conf ...
10net.ipv4.ip_forward = 1
11* Applying /usr/lib/sysctl.d/protect-links.conf ...
12fs.protected_fifos = 1
13fs.protected_hardlinks = 1
14fs.protected_regular = 2
15fs.protected_symlinks = 1
16* Applying /etc/sysctl.conf ...
17net.ipv4.ip_forward = 1

在基本防火墙中添加传输规则

接下来,您将配置您的防火墙,以便在端口 80 上流入您的公共接口(eth0)的流量被转移到您的私人接口(eth1`)。

您在 [前提教程] 中配置的防火墙(https://andsky.com/tech/tutorials/how-to-implement-a-basic-firewall-template-with-iptables-on-ubuntu-20-04)的前进链默认设置为DROP流量. 您需要添加规则,允许您将连接转发到您的 Web 服务器。

前进链中,您将接受用于端口80的新连接,这些连接来自您的公共接口,并前往您的私人接口。

1[environment third]
2sudo iptables -A FORWARD -i eth0 -o eth1 -p tcp --syn --dport 80 -m conntrack --ctstate NEW -j ACCEPT

这将允许第一个包,旨在建立连接,通过防火墙. 您还需要允许任何后续的流量在两个方向,由该连接产生的。 为了允许在您的公共和私人接口之间的ESTABLISHEDRELATED流量,运行以下命令. 首先,您的公共接口:

1[environment third]
2sudo iptables -A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

然后,对于您的私人接口:

1[environment third]
2sudo iptables -A FORWARD -i eth1 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

重复检查前进链上的策略是否设置为DROP:

1[environment third]
2sudo iptables -P FORWARD DROP

在这一点上,你已经允许某些公共和私人接口之间的流量通过你的防火墙,但是,你没有配置规则,实际上会告诉iptables如何翻译和指导流量。

添加 NAT 规则以正确地导向包

接下来,您将添加那些将告诉iptables如何路由您的流量的规则. 您需要执行两个单独的操作,以便iptables正确地更改包,以便客户端可以与Web服务器进行通信。

第一次行动称为 " DNAT " ,将在 " nat " 表的 " PRERUTING " 链中进行。 `DNAT'是改变数据包目的地地址的操作,使其能够在网络之间通过时正确走道。 公共网络上的客户端将会连接到您的防火墙服务器,并且不会了解您的私人网络地貌. 因此,您需要改变每个数据包的目的地地址,以便当它被发送到您的私人网络时,它知道如何正确到达您的网络服务器.

由于您只配置端口转发,而不是在攻击防火墙的每个包上执行 NAT,因此您将希望在您的规则中匹配端口 `80。

1[environment third]
2sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1

这个过程需要照顾一半的图像. 该包应该被正确地路由到您的 Web 服务器. 但是,现在,该包仍然将客户端的原始地址作为源地址. 服务器将尝试直接发送回复到该地址,这将使建立合法的 TCP 连接是不可能的。

< $ > [info] 在 Digital Ocean 上,留下一个不同源地址的 Droplet 包实际上会被超透视器丢出,因此您在此阶段的包甚至永远不会到达网络服务器(通过执行 SNAT 瞬间固定). 这是为防止攻击而采取的一项反渗透措施,因为要求将大量数据通过在请求中伪造来源地址传送到受害人的计算机上。 欲了解更多情况,请阅读我们社区的答复。 < $ > (美元)

要配置正确的路由,您还需要修改包的源地址,因为它离开了防火墙的路由到 Web 服务器. 您需要修改源地址到您的防火墙服务器的私人 IP 地址(10.0.0.2在下面的示例中)。

要启用此功能,请将规则添加到NAT表的POSTROUTING链中,该规则在邮件发送到网络之前被评估。

1[environment third]
2sudo iptables -t nat -A POSTROUTING -o eth1 -p tcp --dport 80 -d 10.0.0.1 -j SNAT --to-source 10.0.0.2

一旦这个规则生效,您的 Web 服务器应该通过指向您的 Web 浏览器到您的防火墙机器的公共地址来访问:

1[environment second]
2curl 203.0.113.2
 1[secondary_label Output]
 2[environment second]
 3<!DOCTYPE html>
 4<html>
 5<head>
 6<title>Welcome to nginx!</title>
 7<style>
 8    body {
 9        width: 35em;
10        margin: 0 auto;
11        font-family: Tahoma, Verdana, Arial, sans-serif;
12    }
13</style>
14</head>
15<body>
16<h1>Welcome to nginx!</h1>
17. . .

您的端口转发设置已完成。

调整永久规则集

现在您已设置端口转发,您可以将其保存到永久规则集。

如果您不介意失去当前规则集中的评论,请使用netfilter-persistent命令使用iptables服务并保存您的规则:

1[environment third]
2sudo service netfilter-persistent save
1[secondary_label Output]
2[environment third]
3 * Saving netfilter rules... run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables save
4run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables save
5                                                                         [ OK ]

如果你想将评论保存在你的文件中,请打开它并手动编辑:

1[environment third]
2sudo nano /etc/iptables/rules.v4

您还需要调整在过滤器表中添加的前进链条规则的配置,以便您可以添加您的PREROUTINGPOSTROUTING规则。

  1[label /etc/iptables/rules.v4]
  2[environment third]
  3*filter
  4# Allow all outgoing, but drop incoming and forwarding packets by default
  5:INPUT DROP [0:0]
  6:FORWARD DROP [0:0]
  7:OUTPUT ACCEPT [0:0]
  8
  9# Custom per-protocol chains
 10:UDP - [0:0]
 11:TCP - [0:0]
 12:ICMP - [0:0]
 13
 14# Acceptable UDP traffic
 15
 16# Acceptable TCP traffic
 17-A TCP -p tcp --dport 22 -j ACCEPT
 18
 19# Acceptable ICMP traffic
 20
 21# Boilerplate acceptance policy
 22-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
 23-A INPUT -i lo -j ACCEPT
 24
 25# Drop invalid packets
 26-A INPUT -m conntrack --ctstate INVALID -j DROP
 27
 28# Pass traffic to protocol-specific chains
 29## Only allow new connections (established and related should already be handled)
 30## For TCP, additionally only allow new SYN packets since that is the only valid
 31## method for establishing a new TCP connection
 32-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
 33-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
 34-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP
 35
 36# Reject anything that's fallen through to this point
 37## Try to be protocol-specific w/ rejection message
 38-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
 39-A INPUT -p tcp -j REJECT --reject-with tcp-reset
 40-A INPUT -j REJECT --reject-with icmp-proto-unreachable
 41
 42# Rules to forward port 80 to our web server
 43
 44# Web server network details:
 45
 46# * Public IP Address: 203.0.113.1
 47# * Private IP Address: 10.0.0.1
 48# * Public Interface: eth0
 49# * Private Interface: eth1
 50# 
 51# Firewall network details:
 52# 
 53# * Public IP Address: 203.0.113.2
 54# * Private IP Address: 10.0.0.2
 55# * Public Interface: eth0
 56# * Private Interface: eth1
 57-A FORWARD -i eth0 -o eth1 -p tcp --syn --dport 80 -m conntrack --ctstate NEW -j ACCEPT
 58-A FORWARD -i eth0 -o eth1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
 59-A FORWARD -i eth1 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
 60# End of Forward filtering rules
 61
 62# Commit the changes
 63
 64COMMIT
 65
 66*raw
 67:PREROUTING ACCEPT [0:0]
 68:OUTPUT ACCEPT [0:0]
 69COMMIT
 70
 71*nat
 72:PREROUTING ACCEPT [0:0]
 73:INPUT ACCEPT [0:0]
 74:OUTPUT ACCEPT [0:0]
 75:POSTROUTING ACCEPT [0:0]
 76
 77# Rules to translate requests for port 80 of the public interface
 78# so that we can forward correctly to the web server using the
 79# private interface.
 80
 81# Web server network details:
 82
 83# * Public IP Address: 203.0.113.1
 84# * Private IP Address: 10.0.0.1
 85# * Public Interface: eth0
 86# * Private Interface: eth1
 87# 
 88# Firewall network details:
 89# 
 90# * Public IP Address: 203.0.113.2
 91# * Private IP Address: 10.0.0.2
 92# * Public Interface: eth0
 93# * Private Interface: eth1
 94-A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1
 95-A POSTROUTING -d 10.0.0.1 -o eth1 -p tcp --dport 80 -j SNAT --to-source 10.0.0.2
 96# End of NAT translations for web server traffic
 97COMMIT
 98
 99*security
100:INPUT ACCEPT [0:0]
101:FORWARD ACCEPT [0:0]
102:OUTPUT ACCEPT [0:0]
103COMMIT
104
105*mangle
106:PREROUTING ACCEPT [0:0]
107:INPUT ACCEPT [0:0]
108:FORWARD ACCEPT [0:0]
109:OUTPUT ACCEPT [0:0]
110:POSTROUTING ACCEPT [0:0]
111COMMIT

保存并关闭文件,一旦添加了内容并调整了值,以反映您自己的网络环境。

接下来,测试您的规则文件的语法:

1[environment third]
2sudo sh -c "iptables-restore -t < /etc/iptables/rules.v4"

如果没有发现错误,请加载规则集:

1[environment third]
2sudo service netfilter-persistent reload
1[secondary_label Output]
2[environment third]
3 * Loading netfilter rules... run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables start
4run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables start
5                                                                         [ OK ]

现在测试您的 Web 服务器是否仍然可以通过防火墙的公共 IP 地址访问:

1[environment second]
2curl 203.0.113.2

这应该像以前一样工作。

结论

在Linux服务器上,您现在应该可以使用 " iptables " 的转发端口。 这一过程涉及允许在内核级别转发,设置访问权限,允许转发防火墙系统上两个接口之间特定端口的流量,并配置NAT规则,使数据包能够正确路由. 这似乎是一个不易操作的过程,但也显示了 " 过滤器 " 包过滤框架和 " 管道 " 防火墙的灵活性。 这可以用来伪装您的私人网络的地貌,同时允许服务流量通过您的网关防火墙机器自由流动.

Published At
Categories with 技术
Tagged with
comments powered by Disqus