iptables/ipset 备忘 - vqiu.cn
2020-10-04 tech linux network iptables 31 mins 11003 字
转自:https://vqiu.cn/ipset-note/,文章有点机翻的痕迹,不过不影响理解。
简介
ipset是iptables的扩展,允许创建一次匹配整个“地址”集的防火墙规则。 与通过线性存储和遍历的普通iptables链不同,IP集存储在索引数据结构中,即使在处理大型集时,查找也非常高效。
ipset只是iptables的扩展,所以本篇文章不仅是ipset的使用笔记,同时也是iptables的使用笔记。
安装
// Debian
apt-get install ipset
//RHEL
yum -y install ipset
12345
快速入门
需求,禁1.1.1.1
与2.2.2.2
IP访问服务器,使用以下iptables 命令可实现:
iptables -A INPUT -s 1.1.1.1 -j DROP
iptables -A INPUT -s 2.2.2.2 -j DROP
同时,我们如果使用ipset也可以实现
ip -N myset iphash
ipset -A myset 1.1.1.1
ipset -A myset 2.2.2.2
iptables -A INPUT -m set --set myset src -j DROP
上面的ipset命令创建了一个带有两个地址(1.1.1.1和2.2.2.2)的新集合( ipset
类型为iphash
)。
然后iptables命令引用带有匹配规范的-m set --set myset src
,这意味着“匹配源头与之匹配(即包含在内)名为myset的集合的数据包”
标志src
表示匹配“源”。 标志dst
将匹配“destination”,并且标志src,dst
将在源和目标上匹配。
在上面的第二个版本中,只需要一个iptables命令,无论该组中包含多少额外的IP地址。 尽管此示例仅使用两个地址,但您可以轻松定义1,000个地址,而基于ipset的配置仍然只需要一个iptables规则,而前一种方法,如果没有ipset的优势,则需要1,000个iptables规则。
应用场景
ipset优点
除了性能提升之外,ipset还允许在许多场景中进行更直接的配置。
如果要定义一个防火墙条件,该条件与1.1.1.1或2.2.2.2中的所有数据包相匹配,并在mychain中继续处理,请注意以下内容不起作用:
iptables -A INPUT -s ! 1.1.1.1 -g mychain
iptables -A INPUT -s ! 2.2.2.2 -g mychain
如果一个数据包来自1.1.1.1,它将与第一个规则不匹配(因为源地址是 1.1.1.1),但它将匹配第二个规则(因为源地址不是 2.2.2.2)。 如果数据包来自2.2.2.2,它将匹配第一个规则(因为源地址不是 1.1.1.1)。 规则相互抵消,所有数据包都匹配,包括1.1.1.1和2.2.2.2。
虽然还有其他方法可以正确构建规则并在没有ipset的情况下实现所需的结果,但没有一种方法可以直观或直接:
ipset -N myset iphash
ipset -A myset 1.1.1.1
ipset -A myset 2.2.2.2
iptables -A INPUT -m set ! --set myset src -g mychain
在上面,如果一个数据包来自1.1.1.1,它将与规则不匹配(因为源地址1.1.1.1与设置的myset匹配)。 如果数据包来自2.2.2.2,则它与规则不匹配(因为源地址2.2.2.2与设置的myset匹配)。
虽然这是一个简单的例子,但它说明了在单个规则中拟合完整条件的基本好处。 在许多方面,单独的iptables规则彼此是相互独立的,并且将单独的规则合并为单个逻辑条件并不总是直截了当,直观或最优,特别是当涉及混合正常和反向测试时。 ipset只是让这些情况下的生活更轻松。
ipset的另一个好处是可以独立于活动的iptables规则来操作集合。 添加/更改/删除条目是一件小事,因为信息简单且顺序无关紧要。 编辑平面列表不需要经过深思熟虑。 另一方面,在iptables中,除了每个规则是一个明显更复杂的对象这一事实之外,规则的顺序至关重要,因此就地规则修改更加繁重且可能容易出错。
配合NAT使用
出站NAT(SNAT或IP伪装)允许专用LAN内的主机访问Internet。 适当的iptables NAT规则匹配源自专用LAN的Internet绑定数据包,并将源地址替换为网关本身的地址(使网关看起来是源主机并隐藏其后面的私有“真实”主机)。
NAT会自动跟踪活动连接,以便将返回的数据包转发回正确的内部主机(通过将目标地址从网关地址更改回原始内部主机的地址)。
以下是执行此操作的简单出站NAT规则的示例,其中10.0.0.0/24是内部LAN:
iptables -t nat -A POSTROUTING \ -o eth0 -j MASQUERADE
事实证明,这是ipset的另一个伟大的应用程序。 假设除了充当本地专用LAN(10.0.0.0/24)的Internet网关之外,您的盒子还可以直接路由到其他四个专用网络(10.30.30.0/24,10.40.40.0/24,192.168.4.0/23和172.22.0.0/22)。 运行以下命令:
ipset -N routed_nets nethash
ipset -A routed_nets 10.30.30.0/24
ipset -A routed_nets 10.40.40.0/24
ipset -A routed_nets 192.168.4.0/23
ipset -A routed_nets 172.22.0.0/22
iptables -t nat -A POSTROUTING \
-s 10.0.0.0/24 \
-m set ! --set routed_nets dst \
-j MASQUERADE
正如您所看到的,ipset可以很容易地确定您想要匹配的内容和不需要的内容。 此规则将伪装从内部LAN(10.0.0.0/24)通过该框的所有流量,除了绑定到routed_nets集中任何网络的数据包,保留对这些网络的正常直接IP路由。 由于此配置完全基于网络地址,因此您不必担心适当的连接类型(VPN的类型,跳数等),也不必担心物理接口和拓扑。
这应该是这样的。 因为这是纯粹的第3层(网络层)实现,所以实现它所需的基础分类也应该是纯层3。
限制某些PC只能访问某些公共主机
让我们说老板担心某些员工在互联网上玩而不是工作,并要求你限制他们的PC访问他们需要能够工作的特定网站,但他不希望这样。影响所有PC(例如他)。
要限制三台PC(10.0.0.5,10.0.0.6和10.0.0.7)只能访问worksite1.com,worksite2.com和worksite3.com,请运行以下命令:
ipset -N limited_hosts iphash
ipset -A limited_hosts 10.0.0.5
ipset -A limited_hosts 10.0.0.6
ipset -A limited_hosts 10.0.0.7
ipset -N allowed_sites iphash
ipset -A allowed_sites worksite1.com
ipset -A allowed_sites worksite2.com
ipset -A allowed_sites worksite3.com
iptables -I FORWARD \
-m set --set limited_hosts src \
-m set ! --set allowed_sites dst \
-j DROP
此示例与单个规则中的两个集匹配。 如果源匹配limited_hosts且目标与allowed_sites不匹配,则丢弃该数据包(因为limited_hosts仅允许与allowed_sites通信)。
请注意,因为此规则位于FORWARD链中,所以它不会影响与防火墙本身之间的通信,也不会影响内部流量(因为该流量甚至不会涉及防火墙)。
阻止除某些PC之外的所有主机的访问(反向场景)
假设老板想阻止访问局域网内所有主机上的一组站点,除了他的PC和他的助手的PC。 对于多样性,在这个例子中,让我们通过MAC地址而不是IP匹配boss和助手PC。 让我们说MAC是11:11:11:11:11:11和22:22:22:22:22:22,其他人阻止的网站是badsite1.com,badsite2.com和badsite3.com 。
代替使用第二个ipset来匹配MAC,让我们利用带有MARK目标的多个iptables命令来标记数据包,以便在同一链中的后续规则中进行处理:
ipset -N blocked_sites iphash
ipset -A blocked_sites badsite1.com
ipset -A blocked_sites badsite2.com
ipset -A blocked_sites badsite3.com
iptables -I FORWARD -m mark --mark 0x187 -j DROP
iptables -I FORWARD \
-m mark --mark 0x187 \
-m mac --mac-source 11:11:11:11:11:11 \
-j MARK --set-mark 0x0
iptables -I FORWARD \
-m mark --mark 0x187 \
-m mac --mac-source 22:22:22:22:22:22 \
-j MARK --set-mark 0x0
iptables -I FORWARD \
-m set --set blocked_sites dst \
-j MARK --set-mark 0x187
正如您所看到的,因为您没有使用ipset来执行上一个示例中的所有匹配工作,所以这些命令更复杂。 因为有多个iptables命令,所以必须认识到它们的顺序非常重要。
请注意,这些规则是使用-I选项(插入)而不是-A(追加)添加的。 插入规则后,它将添加到链的顶部,将所有现有规则向下推。 因为正在插入这些规则中的每一个,所以有效顺序是相反的,因为随着每个规则的添加,它将被插入到前一个规则之上。
上面的最后一个iptables命令实际上成为FORWARD链中的第一个规则。 此规则匹配目标与blocked_sites ipset匹配的所有数据包,然后使用0x187(任意选择的十六进制数)标记这些数据包。 接下来的两条规则仅匹配要排除的主机的数据包以及已标记为0x187的数据包。 然后这两个规则将这些数据包上的标记设置为0x0,“清除”0x187标记。
最后,最后一个iptables规则(由上面的第一个iptables命令表示)丢弃所有具有0x187标记的数据包。 这应该匹配在blocked_sites集中具有目的地的所有数据包,除了来自任一排除的MAC的数据包,因为这些数据包上的标记在达到DROP规则之前被清除。
这只是解决问题的一种方法。 除了使用第二个ipset之外,另一种方法是利用用户定义的链。
如果你想使用第二个ipset而不是mark技术,你将无法达到上述的确切结果,因为ipset没有machash集类型。 但是,有一个macipmap集类型,但这需要在IP和MAC上匹配,而不是像上面那样单独使用MAC。
注意事项:在大多数实际情况中,此解决方案实际上不适用于网站,因为许多可能成为blocked_sites集合的主机(如Facebook,MySpace等)可能有多个IP地址,这些IP可能经常变化。 iptables / ipset的一般限制是只有在解析为单个IP时才应指定主机名。
此外,主机名查找仅在命令运行时发生,因此如果IP地址更改,防火墙规则将不会知道更改,仍将引用旧IP。 因此,实现这些类型的Web访问策略的更好方法是使用HTTP代理解决方案,例如Squid。 该主题显然超出了本文的范围。
自动禁止尝试访问无效服务的主机
ipset还为iptables提供了“目标扩展”,它提供了一种基于任何iptables规则动态添加和删除集合条目的机制。 您无需使用ipset命令手动添加条目,而是可以让iptables随时为您添加条目。
例如,如果远程主机尝试连接到端口25,但您没有运行SMTP服务器,则可能没有任何好处。 要拒绝主持人有机会主动尝试其他任何操作,请使用以下规则:
ipset -N banned_hosts iphash
iptables -A INPUT \
-p tcp --dport 25 \
-j SET --add-set banned_hosts src
iptables -A INPUT \
-m set --set banned_hosts src \
-j DROP
如果数据包到达端口25,比如源地址为1.1.1.1,则会立即将其添加到banned_hosts,就像运行此命令一样:
ipset -A banned_hosts 1.1.1.1
由于DROP规则,从1.1.1.1开始的所有流量都被阻止。
请注意,这也将禁止尝试运行端口扫描的主机,除非他们知道要避免端口25。
清除运行配置
如果要清除ipset和iptables配置(设置,规则,条目)并重置为新的打开防火墙状态(在防火墙脚本的顶部有用),请运行以下命令:
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -t filter -F
iptables -t raw -F
iptables -t nat -F
iptables -t mangle -F
ipset -F
ipset -X
无法销毁“正在使用”的集合,这意味着由一个或多个iptables规则引用(使用ipset -X
)。 因此,为了确保从任何状态完全“重置”,必须首先刷新iptables链(如上所示)。
生产实例
结合生产的SSH,配置如下:
ipset create whitelist-ssh hash:net hashsize 4096
ipset add whitelist-ssh 192.168.10.0/23
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -m set --match-set whitelist-ssh src -p tcp --dport 22 -m comment --comment "Allow Access SSH" -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -m comment --comment "Deny Access SSH" -j DROP
ipset list
iptables -t filter -vxnL
ipset save > /etc/ipset.up.rules
iptables-save > /etc/iptables/rules.v4
//往/etc/rc.local加入以下:
ipset restore < /etc/ipset.up.rules
iptables-restore < /etc/iptables/rules.v4
模拟fail2ban 功能
60秒内访问3次SSH,将源IP禁止60秒
ipset create badguys hash:net timeout 900
ipset add badguys 192.168.0.0/16 nomatch
ipset add badguys 172.16.0.0/16 nomatch
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m set --match-set badguys -j DROP
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 3 --rttl --name SSH -j set --add-set badguys src
或者
ipset create badguys hash:net timeout 900
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m set --match-set badguys src -j DROP
iptables -A INPUT -p tcp --dport 22 -m hashlimit --hashlimit-above 5/min --hashlimit-burst 5 --hashlimit-mode srcip --hashlimit-name SSH-bruteforce -j SET --add-set badguys src
模拟Port Knocking 功能
ipset create knock hash:ip timeout 10
ipset create knock2 hash:ip timeout 10
ipset create whosthere hash:ip timeout 300
iptables -A INPUT -m set --match-set whosthere src -j ACCEPT
iptables -A INPUT -p tcp --dport 1989 -j SET --add-set knock src
iptables -A INPUT -p tcp -m set --match-set knock src --dport 2016 -j SET --add-set knock2 src
iptables -A INPUT -p udp -m set --match-set knock2 src --dport 1864 -j SET --add-set whosthere src
依次按以下敲门
- 1989/TCP
- 2016/TCP
- 1864/UDP
批量禁端口
ipset -N BAD-PORTS bitmap:port range 135-1512
ipset -A BAD-PORTS 135
ipset -A BAD-PORTS 137-139
ipset -A BAD-PORTS 144
ipset -A BAD-PORTS 445
ipset -A BAD-PORTS 1512
iptables -A FORWARD -p tcp -m set --match-set BAD-PORTS dst -j DROP
iptables -A FORWARD -p udp -m set --match-set BAD-PORTS dst -j DROP
或者 对TCP与UDP分别对应
ipset create bl-tcp-ports bitmap:port range 0-65535
ipset create bl-udp-ports bitmap:port range 0-65535
ipset add bl-tcp-ports 23
ipset add bl-tcp-ports 1433
ipset add bl-tcp-ports 2323
ipset add bl-tcp-ports 3306
ipset add bl-tcp-ports 3389
ipset add bl-tcp-ports 5060
定义开放服务端口
- 简单版本
ipset create services bitmap:port range 0-65535
ipset add services 443
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -t filter -A INPUT -p tcp -i ens192 -d 172.16.4.109 -m conntrack --ctstate NEW -m set --match-set services dst -j ACCEPT
- IP + 端口结合 iptables 实现如下:
-A INPUT -s 192.0.2.42 -d 0/0 -p tcp --dport 22 -j ACCEPT
-A INPUT -s 192.0.2.42 -d 0/0 -p tcp --dport 25 -j ACCEPT
-A INPUT -s 198.51.100.54 -d 0/0 -p tcp --dport 22 -j ACCEPT
-A INPUT -s 198.51.100.54 -d 0/0 -p tcp --dport 25 -j ACCEPT
使用ipset 简化
-A INPUT -p tcp -m set --match-set ADMIN_ADDR src -m set --match-set RESTRICTED_PORTS dst -j ACCEPT
ipset create ADMIN_ADDR hash:ip
ipset create RESTRICTED_PORTS bitmap:port
ipset add ADMIN_ADDR 192.0.2.42,198.51.100.54
ipset add RESTRICTED_PORTS 22,25
ipset add ADMIN_ADDR $friend_ip
ipset del ADMIN_ADDR $friend_ip
实现管理员IP白名单功能
ipset create trustedAdminsIP hash:ip
ipset add trustedAdminsIP 192.0.2.1
ipset add trustedAdminsIP 192.0.2.2
ipset list trustedAdminsIP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state ---state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -m set --match-set trustedAdminsIP src -p tcp -m tcp --dport 22 -j ACCEPT
ipset del trustedAdminsIP 192.0.2.2
ipset flush trustedAdminsIP
ipset destroy trustedAdminsIP
或优雅的写法
ipset create whitelist -exist hash:net family inet
ipset add whitelist 119.147.144.176/29
ipset add whitelist 39.108.115.157
iptables -I INPUT 2 -p tcp --dport 22 -m set --match-set whitelist src -j LOG --log-prefix "IP Whitelisted INPUT "
iptables -t filter -I INPUT 3 -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -m set --match-set whitelist src -m comment --comment "Allow Access SSH" -j ACCEPT
IP黑名单功能
ipset create blacklist hash:net
ipset add blacklist 185.93.185.237 -exist
ipset add blacklist 204.2.134.0/24 -exist
ipset add blacklist 208.100.26.228 -exist
iptables -I INPUT 1 -m set --match-set blacklist src -j LOG --log-prefix "IP Blacklisted INPUT"
iptables -I INPUT 2 -m set --match-set blacklist src -j DROP
使用systemd 管理
Unit]
Description=ipset persistent rule service
Before=firewalld.service
ConditionFileNotEmpty=/etc/sysconfig/ipset
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ipset -exist -file /etc/sysconfig/ipset restore
ExecStop=/usr/sbin/ipset -file /etc/sysconfig/ipset save
[Install]
WantedBy=multi-user.target
引用
- [1] http://ipset.netfilter.org/iptables-extensions.man.html
- [2] https://blog.manasg.com/fun-with-ipset-and-iptables/
- [3] http://ipset.netfilter.org/ipset.man.html