防火墙丰富和直接规则:将RHEL 7 Server设置为路由器

时间:2020-03-21 11:43:48  来源:igfitidea点击:

我们将配置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