防火墙丰富和直接规则:将RHEL 7 Server设置为路由器
我们将配置RHEL服务器作为路由器。
伪装,端口转发,丰富和直接的规则将涵盖在内。
测试环境
我们的测试环境中有三台RHEL 7.0服务器可用:
- IPA(10.10.1.79,10.8.8.70)-将配置为路由器,
- srv1(10.8.8.71)-我们DMZ网络上的服务器将用于测试伪装,
- pub(10.10.1.10)-我们公共网络上的服务器将用于测试端口转发。
ipa服务器已将SELinux设置为强制模式。
路由器服务器上的网络接口
ipa服务器具有连接和配置的两个网络接口:
# nmcli d DEVICE TYPE STATE CONNECTION enp0s17 ethernet connected enp0s17 enp0s8 ethernet connected enp0s8 lo loopback unmanaged -
enp0s8连接到我们的“公共”网络10.10.1.0/24,其中enp0s17连接到DMZ 10.8.8.0/24.
# ip -4 ad 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 inet 10.10.1.79/24 brd 10.10.1.255 scope global dynamic enp0s8 valid_lft 86376sec preferred_lft 86376sec 3: enp0s17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 inet 10.8.8.70/24 brd 10.8.8.255 scope global dynamic enp0s17 valid_lft 3583sec preferred_lft 3583sec
路由表如下所示:
# ip ro default via 10.10.1.1 dev enp0s8 proto static metric 1024 10.8.8.0/24 dev enp0s17 proto kernel scope link src 10.8.8.70 10.10.1.0/24 dev enp0s8 proto kernel scope link src 10.10.1.79
排除所有基于iptables的服务:
# systemctl mask iptables ip6tables ebtables ln -s '/dev/null' '/etc/systemd/system/iptables.service' ln -s '/dev/null' '/etc/systemd/system/ip6tables.service' ln -s '/dev/null' '/etc/systemd/system/ebtables.service'
如果未安装iptables-services软件包,则显然在RHEL 7.1和RHEL 7.2中存在一个错误,可以防止iptables服务被屏蔽:
[rhel7.1]# systemctl mask iptables Failed to issue method call: Access denied
[rhel7.1]# cat /var/log/audit/audit.log type=USER_AVC msg=audit(1468920066.358:447): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='avc: denied { disable } for auid=0 uid=0 gid=0 cmdline="systemctl mask iptables ip6tables ebtables" scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=system_u:system_r:init_t:s0 tclass=service exe="/usr/lib/systemd/systemd" sauid=0 hostname=? addr=? terminal=?'
有错误的策略版本是这样的:
[rhel7.1]# rpm -q selinux-policy-targeted selinux-policy-targeted-3.13.1-23.el7.noarch
[rhel7.2]# rpm -q selinux-policy-targeted selinux-policy-targeted-3.13.1-60.el7.noarch
安装iptables-services软件包或者将SELinux置于宽松模式下,可以在RHEL 7.1和RHEL 7.2上屏蔽iptables服务。
防火墙默认区域
这两个网络接口都应添加到区域public:
# firewall-cmd --get-active-zones public interfaces: enp0s17 enp0s8
它应该是默认区域:
# firewall-cmd --get-default-zone public
我们仍然希望将默认区域设置为public(以便我们知道如何更改它),并将接口enp0s17分配给区域dmz。
将默认防火墙区域设置为public,从公共区域中删除网络接口enp0s17,然后将其添加到区域dmz中。
# firewall-cmd --set-default-zone=public # firewall-cmd --remove-interface=enp0s17 --zone=public # firewall-cmd --permanent --add-interface=enp0s17 --zone=dmz
永久配置需要重新加载防火墙配置才能按预期工作:
# firewall-cmd --reload
让我们看一下活动区域:
# firewall-cmd --get-active-zones dmz interfaces: enp0s17 public interfaces: enp0s8
确保在网络脚本中正确设置了区域:
# nmcli con mod enp0s8 connection.zone public # nmcli con mod enp0s17 connection.zone dmz # nmcli c reload
自定义防火墙服务
这部分显示了我们创建自定义防火墙服务的方式。
我们将为iSCSI目标创建一个。
复制现有的firewalld服务配置文件之一,例如对于SSH:
# cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/iscsi-target.xml
打开文件“ /etc/firewalld/services/iscsi-target.xml”进行编辑,然后放置以下内容:
<?xml version="1.0" encoding="utf-8"?> <service> <short>iSCSI Target</short> <description>iSCSI target.</description> <port protocol="tcp" port="3260" </service>
可以通过以下方式将新创建的Firewalld服务添加到dmz区域:
# firewall-cmd --permanent --zone=dmz --add-service iscsi-target
还可以根据需要添加更多服务,例如:
# firewall-cmd --permanent --zone=dmz --add-service={http,https,ldap,ldaps,kerberos,dns,kpasswd,ntp,ftp} # firewall-cmd --reload
列出添加到区域dmz的所有服务:
# firewall-cmd --list-services --zone=dmz dns ftp http https iscsi-target kerberos kpasswd ldap ldaps ntp ssh
列出添加到区域公用中的所有服务:
# firewall-cmd --list-services --zone=public dhcpv6-client
包转发
要配置路由,服务器需要将传入的数据包从一个接口转发到另一个接口。
创建一个新文件“ /etc/sysctl.d/ip_forward.conf”并添加以下内容:
net.ipv4.ip_forward=1
以上使更改永久生效。
现在更改运行时值:
# sysctl -w net.ipv4.ip_forward=1
使用丰富规则进行路由
通常,我们要做的就是在公共界面上伪装。
下面的命令伪装来自区域public中所有主机的数据包:
# firewall-cmd --permanent --zone=public --add-masquerade # firewall-cmd --reload
换句话说,以上内容允许所有流量从区域dmz离开到区域公共。
测试此问题的简单方法是尝试从dmz网络10.8.8.0/24中的任何VM访问某些公共。
我们有一个服务器srv1,位于10.8.8.71上,它的默认路由通过10.8.8.70:
[srv1]# ip ro default via 10.8.8.70 dev mybond0 proto static metric 1024 10.8.8.0/24 dev mybond0 proto kernel scope link src 10.8.8.71
如果我们尝试在禁用伪装的情况下访问example.com,则将具有以下内容:
[srv1]# wget -O - http://example.com --2015-06-18 17:47:30-- http://example.com/ Resolving example.com (example.com)... 93.184.216.34 Connecting to example.com (example.com)|93.184.216.34|:80... failed: No route to host.
启用对公众区域的伪装后,我们可以访问该:
[srv1]# wget http://example.com Resolving example.com (example.com)... 93.184.216.34 Connecting to example.com (example.com)|93.184.216.34|:80... connected. HTTP request sent, awaiting response... 200 OK Length: 1270 (1.2K) [text/html] Saving to: 'index.html' 100%[================================>] 1,270 --.-K/s in 0s 2015-06-18 17:50:19 (129 MB/s) - 'index.html' saved [1270/1270]
如果我们需要进一步控制确切伪装了哪些数据包,则可以添加一个丰富的规则,该规则仅匹配来自特定源地址的数据包,例如:
# firewall-cmd --permanent --zone=public --add-rich-rule='rule family=ipv4 source address=10.8.8.0/24 masquerade' # firewall-cmd --reload
让我们检查丰富的规则:
# firewall-cmd --zone=public --list-all public (default, active) interfaces: enp0s8 sources: services: dhcpv6-client ports: masquerade: yes forward-ports: icmp-blocks: rich rules: rule family="ipv4" source address="10.8.8.0/24" masquerade
使用直接规则进行路由
路由也可以通过直接规则来实现。
但是,带防火墙的手册页指出,直接选项仅在无法使用时才作为最后的选择,例如-add-rich-rule ='rule'。
语法如下:
[--permanent] --direct --add-rule { ipv4 | ipv6 | eb } table chain priority args Add a rule with the arguments args to chain chain in table table with priority priority. The priority is used to order rules. Priority 0 means add rule on top of the chain, with a higher priority the rule will be added further down. Rules with the same priority are on the same level and the order of these rules is not fixed and Jan change. If you want to make sure that a rule will be added after another one, use a low priority for the first and a higher for the following.
为了允许具有私有IP地址的dmz(enp0s17)网络VM与外部网络通信,我们必须配置防火墙以伪装IP:
# firewall-cmd --permanent --direct --add-rule ipv4 nat POSTROUTING 0 -o enp0s8 -j MASQUERADE
将所有ICMP请求从区域dmz(enp0s17)转发到区域public(enp0s8):
# firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -i enp0s17 -o enp0s8 \ -p icmp -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
对所有HTTP和HTTPS流量执行相同的操作:
# firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -i enp0s17 -o enp0s8 \ -p tcp -m multiport --dport 80,443 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
还允许访问公共SMTP和SMTPS服务器:
# firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -i enp0s17 -o enp0s8 \ -p tcp -m multiport --dport 25,465 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
允许通过SSH进入公共服务器:
# firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -i enp0s17 -o enp0s8 \ -p tcp --dport 22 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
记录其他所有内容:
# firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -i enp0s17 -o enp0s8 \ -j LOG --log-prefix "forward_fw "
可选,但不是必需的:
# firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -i enp0s17 -o enp0s8 -j REJECT
重新加载:
# firewall-cmd --reload
检查直接规则:
# firewall-cmd --direct --get-all-rules ipv4 nat POSTROUTING 0 -o enp0s8 -j MASQUERADE ipv4 filter FORWARD 0 -i enp0s17 -o enp0s8 -p icmp -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT ipv4 filter FORWARD 0 -i enp0s17 -o enp0s8 -p tcp -m multiport --dport 80,443 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT ipv4 filter FORWARD 0 -i enp0s17 -o enp0s8 -p tcp -m multiport --dport 25,465 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT ipv4 filter FORWARD 0 -i enp0s17 -o enp0s8 -p tcp --dport 22 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT ipv4 filter FORWARD 0 -i enp0s17 -o enp0s8 -j LOG --log-prefix 'forward_fw '
我们可以使用同一台服务器srv1来测试上述规则。
任何不匹配的内容都应被阻止并记录。
例如,让我们尝试通过FTP访问example.com:
[srv1]# wget -O - ftp://example.com --2015-06-18 18:13:49-- ftp://example.com/ => ‘.listing’ Resolving example.com (example.com)... 93.184.216.34 Connecting to example.com (example.com)|93.184.216.34|:21... failed: No route to host.
日志条目应为:
forward_fw IN=enp0s17 OUT=enp0s8 MAC=08:00:27:ff:70:00:08:00:27:ff:81:00:08:00 SRC=10.8.8.71 DST=93.184.216.34 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=10304 DF PROTO=TCP SPT=34579 DPT=21 WINDOW=14600 RES=0x00 SYN URGP=0
丰富的规则和端口转发
我们可能想通过SSH从公共(10.10.1.0/24)访问dmz网络(10.8.8.0/24)上的服务器。
为此,我们需要放置一些端口转发规则。
下面的规则配置端口转发,以便将与10.10.1.79:2271的连接转发到10.8.8.71:22和SSH日志记录。
# firewall-cmd --permanent --zone=public --add-forward-port='port=2271:proto=tcp:toport=22:toaddr=10.8.8.71' # firewall-cmd --permanent --zone=public --add-rich-rule='rule service name=ssh log prefix="SSH_" level="debug" limit value=1/m reject' # firewall-cmd --reload
让我们看看规则:
# firewall-cmd --list-all --zone=public public (default, active) interfaces: enp0s8 sources: services: dhcpv6-client ports: masquerade: yes forward-ports: port=2271:proto=tcp:toport=22:toaddr=10.8.8.71 icmp-blocks: rich rules: rule service name="ssh" log prefix="SSH_" level="debug" limit value="1/m" reject
要测试端口转发,我们需要一些位于公共网络(10.10.1.0/24)中的服务器:
[pub]$ssh Hyman@theitroad -p2271 The authenticity of host '[10.10.1.79]:2271 ([10.10.1.79]:2271)' can't be established. ECDSA key fingerprint is 32:e6:80:ec:ec:3e:d0:6a:7b:78:bf:6e:79:90:8f:2d. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '[10.10.1.79]:2271' (ECDSA) to the list of known hosts. Hyman@theitroad's password: Last login: Sat Jun 18 17:29:59 2015 from 10.8.8.1
静态路由
如果我们需要创建静态路由来测试某些东西,则可以使用单个bash命令来完成,例如:
# ip route add 10.8.9.0/24 via 10.8.8.70 dev enp0s17