debian11_nftables/ip6tables_限制ipv6公网访问特定端口_centos8/debian仅允许部分IPv4访问端口
<h2 id="debian11_nftablesip6tables_限制ipv6公网访问特定端口_centos8debian仅允许部分ipv4访问端口">debian11_nftables/ip6tables_限制ipv6公网访问特定端口_centos8/debian仅允许部分IPv4访问端口</h2><p><strong>转载注明来源: 本文链接 来自osnosn的博客</strong>,写于 2022-05-28.</p>
<h3 id="参考">参考</h3>
<ul>
<li>【Nftables使用指南】</li>
<li>【wiki-nftables】</li>
<li>【Quick reference-nftables in 10 minutes】</li>
</ul>
<h2 id="限制ipv6公网访问特定端口">限制ipv6公网访问特定端口</h2>
<h3 id="背景环境">背景环境</h3>
<ul>
<li>现在有不少家用的路由器,比如 TPLINK, 华为路由,都已经支持 ipv6 了。<br>
但它们缺省都不允许从外网,通过ipv6访问内部的机器。</li>
<li>这些路由器的防火墙配置。对于ipv4,防火墙有一些端口映射的功能可以设置。对于ipv6,防火墙就只有一个开关。<br>
关闭这个ipv6防火墙开关之后,其实就把内网的机器完全暴露出去了。</li>
<li>这时候,就需要你自己去配置,内网机器自身的防火墙规则,从而保护内网服务器。</li>
</ul>
<h3 id="仅限制tcp端口的ipv6访问">仅限制tcp端口的ipv6访问</h3>
<ul>
<li>这是个简单的例子。只是为了限制某几个端口的ipv6公网访问。</li>
<li>debian 安装 nftables包。激活nftables服务,<code>apt install nftables; systemctl enable nftables;</code>
<ul>
<li>如果系统有什么 restore-iptables 的服务,关掉它。</li>
</ul>
</li>
<li>可以看到 /etc/nftables.conf 中有。<pre><code>#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0; policy accept;
}
chain forward {
type filter hook forward priority 0; policy accept;
}
chain output {
type filter hook output priority 0; policy accept;
}
}
</code></pre>
</li>
<li>只需要加一行变量定义,增加两行规则,就可以针对ipv6,限制端口从外网访问。比如限制22,8888,1080 三个tcp口。改为,<br>
这个规则只影响ipv6,不影响ipv4。<pre><code>#!/usr/sbin/nft -f
define ipv6_ports = { 22,8888,1080 }
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
ct state { established,related } accept
ip6 saddr { fd00::/8, fe80::/64 } tcp dport $ipv6_ports ct state { new, untracked } accept;
ip6 saddr ::/0 tcp dport $ipv6_ports ct state { new, untracked } drop;
}
chain forward {
type filter hook forward priority 0;
}
chain output {
type filter hook output priority 0;
}
}
</code></pre>
</li>
<li>或者加一行变量定义,只加一行规则,更简单。<br>
这个规则只影响ipv6,不影响ipv4。<pre><code>#!/usr/sbin/nft -f
define ipv6_ports = { 22,8888,1080 }
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
ct state { established,related } accept
ip6 saddr != { fd00::/8, fe80::/64 } tcp dport $ipv6_ports ct state { new, untracked } drop;
}
chain forward {
type filter hook forward priority 0;
}
chain output {
type filter hook output priority 0;
}
}
</code></pre>
</li>
<li>增加规则中,可以用 drop,也可用 reject,看你自己喜欢。<br>
drop,访问时,没反应。<br>
reject,访问时,马上返回 Connection refused。</li>
<li><code>policy accept;</code>可以不写,因为默认就是 accept。</li>
<li>修改后,执行 <code>nft -f /etc/nftables.conf</code> 生效。<br>
或者重启整个系统。</li>
</ul>
<h3 id="nft-命令行">nft 命令行</h3>
<p>以上增加的规则,其实对应以下几条命令。</p>
<pre><code>nft insert rule inet filter input ct state { established,related } accept
nft insert rule inet filter input ip6 saddr { fe80::/64,fd00::/8} tcp dport { 22,8888,1080 } ct state { new, untracked } accept
nft add rule inet filter input ip6 saddr ::/0 tcp dport { 22,8888,1080 } ct state { new, untracked } drop
#----分割线,上面两行和下面一行的效果是一样的。二选一。----
nft insert rule inet filter input ct state { established,related } accept
nft add rule inet filter input ip6 saddr != { fe80::/64,fd00::/8} tcp dport { 22,8888,1080 } ct state { new, untracked } drop
</code></pre>
<ul>
<li>nft设置 NAT端口映射例子,还有个参考【NAT 端口映射】。</li>
</ul>
<h3 id="ip6tables-命令行">ip6tables 命令行</h3>
<p>如果系统没装 nftables,只有 iptables。则用下面三条规则。<br>
第一条禁止所有的ipv6访问。后两条允许本地的ipv6访问,插入在第一条前面。</p>
<pre><code>ip6tables -A INPUT -p tcp -m state --state NEW,UNTRACKED--dport 8888 -j DROP
ip6tables -I INPUT -s fd00::/8 -p tcp -m state --state NEW,UNTRACKED--dport 8888 -j ACCEPT
ip6tables -I INPUT -s fe80::/64 -p tcp -m state --state NEW,UNTRACKED--dport 8888 -j ACCEPT
#多个端口,参考这个写法
ip6tables -I INPUT -s fd00::/8 -p tcp -m state --state NEW,UNTRACKED -m multiport --dports 8888,1080 -j ACCEPT
</code></pre>
<p>为了重启系统后,保持有效。有三个办法,任选一种。</p>
<ul>
<li>把三条指令,写入 /etc/rc.local 中。</li>
<li>用 <code>ip6tables-save -f myrule</code> 保存,在 /etc/rc.local 中执行 <code>ip6tables-restore myrule</code> 恢复。</li>
<li>装一个 restore-iptables 的服务,或者试试 <code>apt install iptables-persistent</code> 包。</li>
</ul>
<h2 id="仅允许部分ipv4访问端口">仅允许部分IPv4访问端口</h2>
<h3 id="背景">背景</h3>
<p>需要对部分端口做IP来源限制</p>
<h3 id="centos8-仅允许部分ip访问web端口">centos8 仅允许部分IP访问WEB端口</h3>
<p>系统有 firewalld 服务的情况下。</p>
<pre><code>#------ CLOSE http https FOR ALL BUT iplist ----------
firewall-cmd --new-zone=my_limit --permanent# 创建一个新 zone
firewall-cmd --get-zones
firewall-cmd --reload # 激活这个 zone,否则不能对这个zone操作
firewall-cmd --zone=my_limit --add-source=10.11.22.0/24--permanent# 添加允许的网段
firewall-cmd --zone=my_limit --add-source=10.33.44.0/24--permanent# 添加允许的网段
firewall-cmd --zone=my_limit --add-service http --permanent # 添加允许的服务
firewall-cmd --zone=my_limit --add-service https --permanent
firewall-cmd --remove-service http --permanent #从 public zone 移除服务
firewall-cmd --remove-service https --permanent
firewall-cmd --reload
#------ OPEN http https FOR ALL ----------
firewall-cmd --zone=my_limit --remove-service http --permanent #从my_limit 中移除服务
firewall-cmd --zone=my_limit --remove-service https --permanent
firewall-cmd --add-service http --permanent # 在public中添加服务
firewall-cmd --add-service https --permanent
firewall-cmd --reload
#-----other cmd-----------
firewall-cmd --zone=my_limit --remove-source=10.11.22.0/24 #移除允许的网段
firewall-cmd --zone=my_limit --list-sources #查看my_limit 中的ip
firewall-cmd --zone=my_limit --list-all #查看my_limit 的所有
firewall-cmd --list-all-zones
#--------------------------
</code></pre>
<h3 id="debian-仅允许部分ip访问web端口">debian 仅允许部分IP访问WEB端口</h3>
<ul>
<li>debian 安装 <code>iptables</code> 包之后。
<ul>
<li>iptables 命令生成,其实用的是 <code>xtables-nft-multi</code>命令。<br>
这个命令是把 iptables的规则命令,翻译为 nft规则命令,写入nftables中。</li>
<li>iptables-legacy 命令是 <code>xtables-legacy-multi</code>,才是真正的,老的iptables命令。</li>
<li>一旦执行过iptables-legacy,内核会加载 <code>iptable_filter</code>模块。<br>
再执行iptables,就会给出<code>Warning</code>,说有旧模式的iptables在使用。</li>
</ul>
</li>
<li>从iptables规则直接翻译为nft规则,其实并不好用。nft的很多高级特性都用不上。<br>
还不如安装 <code>nftables</code> 包,直接用原生的 nft规则编写。</li>
</ul>
<h4 id="iptables命令行-ipv4">iptables命令行 ipv4</h4>
<ul>
<li>限制本机的端口<pre><code>iptables -A INPUT -p tcp -m state --state NEW,UNTRACKED--dport 80 -j DROP
iptables -I INPUT -s 202.123.123.0/24 -p tcp -m state --state NEW,UNTRACKED--dport 80 -j ACCEPT
#多端口写法
#iptables -A INPUT -p tcp -m state --state NEW,UNTRACKED -m multiport --dports 80,443 -j REJECT
</code></pre>
</li>
<li>有的系统没有<code>-m state --state</code>就换<code>-m conntrack --ctstate</code>这两没区别,是一样的。</li>
<li>限制所有tcp端口<code>iptables -A INPUT -p tcp -m state --state NEW,UNTRACKED -j DROP</code></li>
<li>为了方便维护/修改,可以创建一个自定义chain,然后把上面的规则都写入到这个自定义chain中。<br>
需要修改时,<code>iptables -F port_limit</code>直接清空这个chain的内容,重新添加规则。<pre><code>iptables -t filter -N port_limit #自定义chain
iptables -t filter -I INPUT -j port_limit #插入INPUT表中,第一条
</code></pre>
</li>
<li>限制nat转发端口<br>
在 FORWARD 中限制。<pre><code>iptables -t filter -N port_forward #自定义chain
iptables -t filter -I FORWARD -j port_forward #插入FORWORD表中
iptables -I port_forward -s 202.123.123.0/24 -m state -o virbr0 -d 192.168.122.0/24 --state NEW,UNTRACKED -j ACCEPT
</code></pre>
或在 nat 的 PREROUTING 中限制。</li>
<li>在 filter 的 INPUT 中,对nat端口是无效的。<br>
因为数据包被prerouting 处理后(目标非本地的包)转向了 forward表,不经过input表。</li>
</ul>
<h4 id="nft-命令行-ipv4">nft 命令行 ipv4</h4>
<ul>
<li>限制本机的端口<br>
具体的插入位置,用<code>nft list ruleset</code>查看,自己机器中已有的 nft chain,找到 filter hook input 的 chain。<br>
没有的话,自己创建一个chain。<br>
在我机器上,在 <code>table ip filter { chain INPUT { type filter hook input priority 0; } }</code><pre><code>nft insert rule ip filter INPUT ip saddr {202.123.123.0/24, 123.23.23.0/24} ct state { new, untracked } tcp dport {80,443} counter accept
nft add rule ip filter INPUT ct state { new, untracked } tcp dport {80,443} counter reject
</code></pre>
</li>
<li>限制所有tcp端口<code>nft add rule ip filter INPUT meta l4proto tcp ct state { new, untracked } counter reject</code></li>
<li>为了方便维护/修改,可以创建一个自定义chain,然后把上面的规则都写入到这个自定义chain中。<br>
需要修改时,<code>nft flush chain ip filter port_limit</code>直接清空这个chain的内容,重新添加规则。<pre><code>nft add chain ip filter port_limit #自定义chain
nft insert rule ip filter INPUT jump port_limit #插入INPUT表中,第一条
</code></pre>
</li>
<li>限制nat转发端口<br>
类似,找到 filter hook forward 的 chain,写入转发规则限制即可。<br>
没有的话,自己创建一个chain。<br>
在我机器上,在 <code>table ip filter { chain FORWARD { type filter hook forward priority 0; } }</code><pre><code>nft add chain ip filter port_forward #自定义chain
nft insert rule ip filter FORWARD jump port_forward #插入FORWORD表中
nft insert rule ip filter port_forward oifname "virbr0" ip saddr {202.123.123.0/24, 123.23.23.0/24} ip daddr 192.168.122.0/24 ct state new counter accept
</code></pre>
</li>
</ul>
<h4 id="nft-本地端口重定向">nft 本地端口重定向</h4>
<ul>
<li>需要<code>nat hook prerouting</code>的chain,通常没有,自己创建一个chain。<pre><code>nft add table ip nat
nft add chain ip nat prerouting '{ type nat hook prerouting priority dstnat ; }'
nft add rule ip nat prerouting tcp dport 1234 redirect to :22
</code></pre>
如果要限制来源ip,在input chain中限制 22口就可以了。目的地,为本机的数据包,是要经过 input表的,到达input表时,目标端口已经是 22。</li>
<li>iptables<pre><code>iptables -t nat -A PREROUTING -p tcp --dport 1234 -j REDIRECT --to-port 22
</code></pre>
</li>
</ul>
<h3 id="openwrt-在-fw4-中使用-ipset-匹配来源-ip">OpenWRT 在 fw4 中使用 ipset 匹配来源 IP</h3>
<ul>
<li><strong>op-22 使用的是 fw4,即 nft。</strong><br>
op-21 以及之前的版本用的是 fw3,即 iptables。</li>
<li>op-22.03.03,<code>luci-app-firewall - git-23.035.45612</code>。<br>
web luci页面,无法配置 ipset,也无法把 ipset 配置到规则中使用。<br>
只能手工编辑 firewall 配置文件,或者使用 "uci" 命令配置。</li>
<li><strong>升级<code>luci-app-firewall</code>到最新,web luci 就有 ipset的配置</strong>。<br>
用命令升级,<code>opkg upgrade luci-app-firewall</code>。
<ul>
<li><code>luci-app-firewall - git-23.089.66165</code><br>
<code>luci-app-firewall - git-23.093.42704</code>(目前最新的版本)。<br>
web luci页面就可以配置 ipset。IP列表文件 上传到 <code>/etc/luci-uploads/</code>目录中。<br>
ipset 配置中,<code>Packet Field Match</code>只能选取一个,不能填写 comment,否则出错。<br>
不支持 iprange。<br>
规则配置中,高级设置,<strong>有"Use ipset"的选项</strong>。</li>
</ul>
</li>
<li>无论 web luci是否支持 ipset配置,<strong>手工设置</strong>总是 <strong>有效的</strong>。</li>
<li><strong>fw4 下,使用 ipset</strong>。【官方文档 IP sets】,【官方例子 fw3_config_ipset】<br>
以下是针对<code>luci-app-firewall - git-23.035.45612</code>,web luci无 ipset配置。<br>
使用 手工编辑 firewall 配置文件,或者使用 "uci" 命令配置。
<ul>
<li>在 <code>/etc/config/firewall</code> 添加以下配置行。<pre><code>config ipset
option name 'main_allowed'
option family 'ipv4'
option match 'src_net' #支持网段 和 IP
#option match 'net' #rule 中要指定 src 或 dest
#option match 'src_ip' #仅支持 IP。不识别网段。
##option maxelem '256' #不需设置,除非这个ipset会 动态添加element
option enabled '1'
list entry '10.12.34.0/24'
option loadfile '/root/net_list.txt'
</code></pre>
net_list.txt 文件如下,<pre><code># 支持 空行,支持 注释。 空行和注释会被忽略
10.12.45.0/24
10.34.56.78
10.45.67.0/24
</code></pre>
"list entry" 和 "option loadfile" 可以混用。结果是它们的<strong>"合集"</strong>。<br>
用命令<code>fw4 check</code>检查无错误。用命令<code>fw4 restart</code>重启防火墙。</li>
<li>"match" 是 <strong>"net"</strong>,支持网段/IP。会在<code>table inet fw4 {}</code>中生成一个集合 set,<br>
<code>set main_allowed { type ipv4_addr; flags interval; auto-merge; }</code></li>
<li>"match" 是 <strong>"ip"</strong>,仅支持IP,写网段也会 识别为 IP。生成的集合 set,<br>
则是 <code>set main_allowed { type ipv4_addr; }</code></li>
<li><code>option maxelem '0'</code> <strong>正常 不设置</strong>,默认值是 0,添加的条目没限制。似乎也不会预分配内存,没见到内存空间占用变大。<br>
<strong>如果设置</strong>,会限制添加条目的数量,似乎还会预分配内存。如果设置 65536,会见到内存占用升高。(2023-04测试,op22.03.3, luci-app-firewall git-23.035)<br>
如果某个 rule 会<strong>动态添加</strong>条目到这个 ipset,就<strong>必须设置</strong>,限制一下数量,防止条目太多而内存溢出。</li>
<li>uci 的例子。<pre><code>uci batch << EOI
add firewall ipset
#set firewall.main_allowed='ipset'
set firewall.@ipset[-1].name="main_allowed"
set firewall.@ipset[-1].match="src_net"
set firewall.@ipset[-1].enabled="1"
add_list firewall.@ipset[-1].entry="10.12.34.0/24"
set firewall.@ipset[-1].loadfile="/root/net_list.txt"
commit firewall
EOI
</code></pre>
</li>
<li>在 <code>/etc/config/firewall</code> 中,找到<strong>需要匹配来源 IP 的 rule</strong>,<br>
删除这个 rule中 所有的<code>list src_ip ...</code>,<br>
加入一行<code>option ipset 'main_allowed src'</code>。<br>
例子如下,<pre><code>config rule
option name 'web-server'
option ipset 'main_allowed src'#无论 ipset中是否有定义,都按照 src匹配。
#option ipset 'main_allowed' #按照ipset 的 match定义中的src或dest。如无,默认是src。
#option ipset '!main_allowed src'#“!”后有无空格都行,匹配 不在ipset中的IP。
option target 'ACCEPT'
option dest_port '80 443'
option src '*'
</code></pre>
重启防火墙生效。<code>/etc/init.d/firewall restart</code> 或 <code>fw4 restart</code>。
<ul>
<li>如果<code>list src_ip ...</code>和<code>option ipset</code>混用,结果是要满足两种配置的<strong>"交集"</strong>才能访问。</li>
</ul>
</li>
<li>手工配置好 ipset 之后。在 web luci 中也<strong>见不到</strong>这个 ipset。(2023-04测试,op22.03.3, luci-app-firewall git-23.035)</li>
<li>上面的这个"web-server"规则。在 web luci 的 "Traffic Rules" 中,能<strong>见到</strong>这个 rule,但<strong>见不到</strong> ipset的设置。<br>
在 web luci 中<strong>修改</strong>这个"web-server"规则,<strong>不会丢失</strong><code>option ipset</code>的配置。(2023-04测试,op22.03.3, luci-app-firewall git-23.035)<br>
添加 "source address" 等于添加 <code>list src_ip '4.3.2.0/24'</code>,会导致实际的来源 IP,必须匹配 两种配置的<strong>"交集"</strong>。<br>
因为rule是这样的<code>ip saddr { 4.3.2.0/24 } tcp dport { 80, 443 } ip saddr @main_allowed counter accept</code><br>
<strong>清空</strong> "source address",<strong>不丢失</strong><code>option ipset</code>的配置,规则还是最初的效果。</li>
</ul>
</li>
<li><strong>fw4 还支持 <code>config include</code> 添加自定义 rule。</strong><br>
见【官方文档 includes_for_2203_and_later_with_fw4】。</li>
<li><strong>fw4</strong> 的 web luci 界面,配置 ipset <strong>不支持 iprange</strong>,(目前最新是 luci-app-firewall git-23.093)。<br>
而 "match" 是 <strong>"net"</strong> 时,生成集合 set 是包含 <strong>"flags interval"</strong>,即支持iprange。<br>
可以通过以下两种办法(二选一),添加 ipset 的 element,使用iprange。<br>
假设你在 web luci 中,添加一个 ipset,名称是 "main_allowed"。
<ul>
<li>或,创建文件 <code>/usr/share/nftables.d/ruleset-post/add-element.nft</code>,如果对应目录不存在,则自己创建目录。<pre><code># file: add-element.nft
add element inet fw4 main_allowed { 10.12.45.100-10.12.45.200}
</code></pre>
</li>
<li>或,在 /etc/config/firewall 中添加,<pre><code>config include
option enabled 1
option type 'script'
option path '/etc/add-ipset-element.sh'
option fw4_compatible 1
</code></pre>
<pre><code>#!/bin/sh
# file: add-ipset-element.sh
nft add element inet fw4 main_allowed { 10.12.45.100-10.12.45.200}
</code></pre>
</li>
</ul>
</li>
</ul>
<h3 id="pve-的防火墙配置">PVE 的防火墙配置</h3>
<ul>
<li>见【ProxmoxVE_PVE防火墙_本机静态路由_本机端口转发_修改默认8006端口_旁路由VM】。</li>
</ul>
<h2 id="禁止某ip访问特定端口">禁止某ip访问特定端口</h2>
<ul>
<li>并统计数据包:<br>
<code>nft add rule inet filter input ip saddr 170.64.134.97 tcp dport 22 counter drop</code></li>
</ul>
<h2 id="限制sshd的登录">限制sshd的登录</h2>
<ul>
<li>安装 fail2ban 来防止无限制(次数)猜密码。或者用防火墙规则,限制连接数。<br>
参考【Debian10_Centos8_fail2ban_sshd算法_限制连接数】</li>
</ul>
<h2 id="其他">其他</h2>
<ul>
<li>删除 nft 的 rule<pre><code>nft -a list ruleset#找出 handle值 xxxx
nft delete rule inet filter output handle xxxx
</code></pre>
</li>
</ul>
<p>----end----</p>
<hr>
<p><strong>转载注明来源: 本文链接 https://www.cnblogs.com/osnosn/p/16320603.html</strong><br>
<strong>来自 osnosn的博客 https://www.cnblogs.com/osnosn/</strong> .</p>
<hr><br><br>
来源:https://www.cnblogs.com/osnosn/p/16320603.html
頁:
[1]