Nftables 防火墙端口策略
服务器上搭建了KMS激活服务器,但是由于国外版权保护和DMCA 限制,我需要限制国外ip访问我的服务器1688 端口,网上大部分关于这方面问题的教程采取了ipset + iptables 的解决方案,暂无nftables解决方案,所以写一篇供大家参考。
获取nft_geoip 脚本
来源: https://wiki.nftables.org/wiki-nftables/index.php/GeoIP_matching
构建定时更新脚本
1
| # sudo vim /etc/systemd/system/nft-geoip.service
|
1 2 3 4 5 6 7 8
| [Unit] Description=Nftables GeoIP
[Service] User=root Type=oneshot ExecStart=/usr/bin/python3 /opt/script/nft-geoip/nft_geoip.py --file-location /opt/script/nft-geoip/location.csv -d -o /etc/nft.d/ ExecStartPost= /usr/sbin/nft -f /etc/nftables.conf
|
1
| # sudo vim /etc/systemd/system/nft-geoip.timer
|
1 2 3 4 5 6 7 8 9 10
| [Unit] Description=Every Friday AM 3:00 renewal of nftables geoip
[Timer] OnCalendar=Fri *-*-* 03:00:00 RandomizedDelaySec=1h Persistent=true
[Install] WantedBy=timers.target
|
参考配置
nftables 引用geoip区域文件做区域限制
给出我的 inet filter input 示例以供参考:
载入文件较大,需要超过 300M 的可用内存空间!!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #!/usr/sbin/nft -f # vim:set ts=2 sw=2 et:
# IPv4/IPv6 Simple & Safe firewall ruleset. # More examples in /usr/share/nftables/ and /usr /share/doc/nftables/examples/.
# A simple firewall
flush ruleset
table inet filter { include "/etc/nft.d/geoip-def-all.nft" include "/etc/nft.d/geoip-ipv4.nft" include "/etc/nft.d/geoip-ipv6.nft" chain input { type filter hook input priority 0; policy drop;
# insert geoip map meta mark set ip saddr map @geoip4 meta mark set ip6 saddr map @geoip6
# established/related connections ct state established,related accept
# invalid connections # ct state invalid drop
# loopback interface iif lo accept
# ICMP & IGMP ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept ip protocol icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } accept ip protocol igmp accept ip protocol icmp accept
# SSH (port 22) # recommend nftables geoip zones limit meta mark $CN tcp dport ssh log prefix "cn-zones-ssh-accept" counter packets 0 bytes 0 accept
# HTTP (ports 80 & 443) tcp dport { http, https } accept # vlmcsd -- Windows Key Management Services # recommend nftables geoip zones limit meta mark $CN tcp dport 1688 log prefix "cn-zones-kms-accept" counter packets 0 bytes 0 accept # count and drop any other traffic counter packets 0 bytes 0 drop } }
|
效果展示
如图:
错误示例:
网上有大量从apnic获取国内ip地址端的示例:
1
| cn_ipv4=$(curl http://ftp.apnic.net/stats/apnic/delegated-apnic-latest | awk -F '|' '/CN/&&/ipv4/ {print $4 "/" 32-log($5)/log(2)}' )
|
错误示例: cn_ipv6=$(curl http://ftp.apnic.net/stats/apnic/delegated-apnic-latest | awk -F ‘|’ ‘/CN/&&/ipv6/ {print $4 “/“ 32-log($5)/log(2)}’ )
1
| cn_ipv6=$(curl http://ftp.apnic.net/stats/apnic/delegated-apnic-latest | awk -F '|' '/CN/&&/ipv6/ {print $4 "/" $5 }'
|
ipv4 子网掩码可通过 32- 分配位数2的对数取余 获取,ipv6 掩码也这么算,明显是错误的,例如会算出这样一个奇怪的掩码:
可见,大部分都,没有思考ipv4 地址端计算方式,
ipv6 合适的地址段表示:
1 2 3 4
| apnic|CN|ipv6|2001:7fa:5::|48|20031106|assigned 转换为: 2001:7fa:5::-2001:7fa:5:ffff:ffff:ffff:ffff:ffff 2001:7fa:5::/48
|
F & A:
debian 12 自带的防火墙为nft,并且主流发行版新版本后端都采用了nft,这篇文章是学习nft用法。另外nft 可以省略ip6tables 规则的书写,直接使用inet表覆盖了ip和ip6.
性能比较见 redhat-benchmarking-nftables
可见iptables如果规则写的好,不要有太多的jump和goto,性能甚至比nftables略胜一筹
可以使用iptables + ipset 实现,你可以google搜索,相信相关blog很多。