使用Iptables将CentOS 6 Linux服务器设置为路由器
将CentOS Linux服务器配置为路由器。
什么是Iptables?
iptables是一个用户空间应用程序,允许用户配置Linux内核防火墙提供的表(实现为不同的Netfilter模块)以及它存储的链和规则。
换句话说,iptables是用于管理Linux防火墙规则的工具。
Iptables应该随所有Linux发行版一起提供。
Linux路由器配置
我们的CentOS服务器具有如下配置的2个网卡:
- eth0:从eth1的角度来看网络的外部,配置了静态IP地址10.10.1.20,
- eth1:内部(LAN)网络,配置了静态IP地址10.8.8.2.
然后,通过家用路由器自然对10.10.1.0/24网络进行进一步的NAT,以可以访问Internet。
这不在这里。
我们想要实现的是:
- 专用网络10.8.8.0/24上的服务器必须能够ping通外部IP,
- 专用网络10.8.8.0/24上的服务器必须能够通过HTTP/HTTPS访问公共网络服务器,
- 从私有网络10.8.8.0/24到公众的所有其他传出流量都应被拒绝,
- 公用网络10.10.1.0/24上的服务器必须能够通过HTTP/HTTPS访问专用网络10.8.8.0/24上的网络服务器,
- 公用网络10.10.1.0/24上的服务器必须能够通过SSH连接到专用网络,
- 从公用网络10.10.1.0/24到专用10.8.8.0/24的所有其他传入流量都应记录并拒绝。
下图可能有助于了解网络配置。
有关更多信息,请使用VirtualBox检查Linux测试环境环境。
启用转发
在CentOS服务器上启用IP转发:
# sed -i 's/net.ipv4.ip_forward = 0/net.ipv4.ip_forward = 1/' /etc/sysctl.conf # sysctl -p
路由表如下所示:
# ip ro 10.10.1.0/24 dev eth0 proto kernel scope link src 10.10.1.20 10.8.8.0/24 dev eth1 proto kernel scope link src 10.8.8.2 default via 10.10.1.1 dev eth0
默认网关在“公共” eth0接口上。
配置正向链(过滤器表)
我们希望内部网络(eth1)上的计算机能够ping通公共服务器。
因此,我们需要允许所有源自eth1的新ICMP流量都通过eth0离开:
# iptables -A FORWARD -i eth1 -o eth0 -p icmp -m state --state NEW -j ACCEPT
我们还希望内部(eth1)网络上的服务器能够在HTTP和HTTPS端口上启动与公共Web服务器的连接:
# iptables -A FORWARD -s 10.8.8.0/24 -i eth1 -o eth0 -p tcp -m multiport --dports 80,443 -m state --state NEW -j ACCEPT
请注意,此处不是强制性的源网络地址定义。
另一方面,如果我们要自己托管一些私有Web服务器,我们希望能够从公共(eth0)网络访问它们:
# iptables -A FORWARD -d 10.8.8.0/24 -i eth0 -o eth1 -p tcp -m multiport --dports 80,443 -m state --state NEW -j ACCEPT
我们还希望能够通过SSH连接到专用(eth1)网络:
# iptables -A FORWARD -d 10.8.8.0/24 -i eth0 -o eth1 -p tcp -m multiport --dports 22 -m state --state NEW -j ACCEPT
然后,我们要允许所有已经建立的或者相关的连接,两种方式:
# iptables -A FORWARD -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT
最后,在删除之前,我们将记录其他所有内容以进行故障排除:
# iptables -A FORWARD -p tcp -j LOG --log-prefix "iptables_forward " # iptables -A FORWARD -p tcp -j DROP
这是过滤器表正向链的最终iptables配置:
# iptables -S FORWARD -P FORWARD ACCEPT -A FORWARD -i eth1 -o eth0 -p icmp -m state --state NEW -j ACCEPT -A FORWARD -s 10.8.8.0/24 -i eth1 -o eth0 -p tcp -m multiport --dports 80,443 -m state --state NEW -j ACCEPT -A FORWARD -d 10.8.8.0/24 -i eth0 -o eth1 -p tcp -m multiport --dports 80,443 -m state --state NEW -j ACCEPT -A FORWARD -d 10.8.8.0/24 -i eth0 -o eth1 -p tcp -m multiport --dports 22 -m state --state NEW -j ACCEPT -A FORWARD -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT -A FORWARD -p tcp -j LOG --log-prefix "iptables_forward " -A FORWARD -p tcp -j DROP
配置NAT表:预路由链
预路由链有助于将数据包的目标IP地址转换为与本地服务器上的路由相匹配的内容。
这用于目标NAT(DNAT)。
在以下示例中,我们要将端口22043上的所有SSH通信转发到10.8.8.43计算机的本地端口22:
# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 22043 -m comment --comment "DNAT SSH for .43" -j DNAT --to-destination 10.8.8.43:22
现在,如果我们尝试初始化从外部(eth0)网络到10.10.1.20:22043的SSH连接,我们应该能够在端口22上访问10.8.8.43的计算机。
可以添加与上述类似的更多DNAT规则,例如,访问位于10.8.8.44:80上的端口8080上的HTTP Web服务器:
# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination 10.8.8.44:80
我们应该知道这个主意。
配置NAT表:路由后链
后路由链有助于将数据包的源IP地址转换为可能与目标服务器上的路由匹配的地址。
这用于源NAT(SNAT)。
现在,为了允许具有私有IP地址的私有(eth1)网络节点与外部公共网络进行通信,我们必须配置防火墙以进行IP伪装,该防火墙可以屏蔽来自具有防火墙外部设备IP地址的LAN节点的请求(在这种情况下, ,eth0):
# iptables -t nat -A POSTROUTING -o eth0 -p icmp -j MASQUERADE # iptables -t nat -A POSTROUTING -o eth0 -p tcp -m multiport --dports 80,443 -j MASQUERADE
这是NAT表(所有链)的最终iptables配置:
# iptables -t nat -S -P PREROUTING ACCEPT -P POSTROUTING ACCEPT -P OUTPUT ACCEPT -A PREROUTING -i eth0 -p tcp -m tcp --dport 22043 -m comment --comment "DNAT SSH for .43" -j DNAT --to-destination 10.8.8.43:22 -A POSTROUTING -o eth0 -p icmp -j MASQUERADE -A POSTROUTING -o eth0 -p tcp -m multiport --dports 80,443 -j MASQUERADE
不要忘记保存iptables规则:
# service iptables save
Puppet类来管理防火墙规则
以下Puppet类可以用作管理防火墙规则的示例。
查看此教程 文章,了解如何在CentOS上配置Puppet服务器。
class fw_router_forward_puppet { firewall { '001R ICMP': chain => 'FORWARD', state => ['NEW'], iniface => 'eth1', outiface => 'eth0', proto => 'icmp', action => 'accept' } firewall { '002R Outgoing HTTP/S': chain => 'FORWARD', state => ['NEW'], iniface => 'eth1', outiface => 'eth0', proto => 'tcp', source => '10.8.8.0/24', dport => [ 80, 443 ], action => 'accept' } firewall { '003R Incoming HTTP/S': chain => 'FORWARD', state => ['NEW'], iniface => 'eth0', outiface => 'eth1', proto => 'tcp', destination => '10.8.8.0/24', dport => [ 80, 443 ], action => 'accept' } firewall { '004R Incoming SSH': chain => 'FORWARD', state => ['NEW'], iniface => 'eth0', outiface => 'eth1', proto => 'tcp', destination => '10.8.8.0/24', dport => [ 22 ], action => 'accept' } firewall { '997R ': chain => 'FORWARD', state => ['RELATED', 'ESTABLISHED'], action => 'accept', } firewall { '998R LOG sessions': chain => 'FORWARD', jump => 'LOG', log_level => '4', log_prefix => 'iptables_forward ', } firewall { '999R Drop all': chain => 'FORWARD', action => 'drop', } } class fw_router_prerouting_puppet { firewall { '005R Route ICMP': chain => 'POSTROUTING', table => 'nat', outiface => 'eth0', proto => 'icmp', jump => 'MASQUERADE' } firewall { '006R Route HTTP/S': chain => 'POSTROUTING', table => 'nat', outiface => 'eth0', proto => 'tcp', dport => [ 80, 443 ], jump => 'MASQUERADE' } firewall { '007R NAT HTTP for VIP .35': chain => 'PREROUTING', table => 'nat', iniface => 'eth0', proto => 'tcp', dport => [ 8035 ], todest => '10.8.8.35:80', jump => 'DNAT' } firewall { '008R NAT HTTPS for VIP .35': chain => 'PREROUTING', table => 'nat', iniface => 'eth0', proto => 'tcp', dport => [ 8835 ], todest => '10.8.8.35:443', jump => 'DNAT' } firewall { '011R NAT SSH for .43': chain => 'PREROUTING', table => 'nat', iniface => 'eth0', proto => 'tcp', dport => [ 22043 ], todest => '10.8.8.43:22', jump => 'DNAT' } }