osnosn

  博客园 :: 首页 :: 博问 :: 闪存 :: :: 联系 :: 订阅 订阅 :: 管理 ::

debian11_nftables/ip6tables_限制ipv6公网访问特定端口_centos8/debian仅允许部分IPv4访问端口

转载注明来源: 本文链接 来自osnosn的博客,写于 2022-05-28.

参考

限制ipv6公网访问特定端口

背景环境

  • 现在有不少家用的路由器,比如 TPLINK, 华为路由,都已经支持 ipv6 了。
    但它们缺省都不允许从外网,通过ipv6访问内部的机器。
  • 这些路由器的防火墙配置。对于ipv4,防火墙有一些端口映射的功能可以设置。对于ipv6,防火墙就只有一个开关。
    关闭这个ipv6防火墙开关之后,其实就把内网的机器完全暴露出去了。
  • 这时候,就需要你自己去配置,内网机器自身的防火墙规则,从而保护内网服务器。

仅限制tcp端口的ipv6访问

  • 这是个简单的例子。只是为了限制某几个端口的ipv6公网访问。
  • debian 安装 nftables包。激活nftables服务,apt install nftables; systemctl enable nftables;
    • 如果系统有什么 restore-iptables 的服务,关掉它。
  • 可以看到 /etc/nftables.conf 中有。
    #!/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;
      }
    }
    
  • 只需要加一行变量定义,增加两行规则,就可以针对ipv6,限制端口从外网访问。比如限制22,8888,1080 三个tcp口。改为,
    这个规则只影响ipv6,不影响ipv4。
    #!/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;
      }
    }
    
  • 或者加一行变量定义,只加一行规则,更简单。
    这个规则只影响ipv6,不影响ipv4。
    #!/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;
      }
    }
    
  • 增加规则中,可以用 drop,也可用 reject,看你自己喜欢。
    drop,访问时,没反应。
    reject,访问时,马上返回 Connection refused。
  • policy accept;可以不写,因为默认就是 accept。
  • 修改后,执行 nft -f /etc/nftables.conf 生效。
    或者重启整个系统。

nft 命令行

以上增加的规则,其实对应以下几条命令。

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

ip6tables 命令行

如果系统没装 nftables,只有 iptables。则用下面三条规则。
第一条禁止所有的ipv6访问。后两条允许本地的ipv6访问,插入在第一条前面。

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

为了重启系统后,保持有效。有三个办法,任选一种。

  • 把三条指令,写入 /etc/rc.local 中。
  • ip6tables-save -f myrule 保存,在 /etc/rc.local 中执行 ip6tables-restore myrule 恢复。
  • 装一个 restore-iptables 的服务,或者试试 apt install iptables-persistent 包。

仅允许部分IPv4访问端口

背景

需要对部分端口做IP来源限制

centos8 仅允许部分IP访问WEB端口

系统有 firewalld 服务的情况下。

#------ 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
#--------------------------

debian 仅允许部分IP访问WEB端口

  • debian 安装 iptables 包之后。
    • iptables 命令生成,其实用的是 xtables-nft-multi命令。
      这个命令是把 iptables的规则命令,翻译为 nft规则命令,写入nftables中。
    • iptables-legacy 命令是 xtables-legacy-multi,才是真正的,老的iptables命令。
    • 一旦执行过iptables-legacy,内核会加载 iptable_filter模块。
      再执行iptables,就会给出Warning,说有旧模式的iptables在使用。
  • 从iptables规则直接翻译为nft规则,其实并不好用。nft的很多高级特性都用不上。
    还不如安装 nftables 包,直接用原生的 nft规则编写。

iptables命令行 ipv4

  • 限制本机的端口
    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
    
  • 有的系统没有-m state --state就换-m conntrack --ctstate这两没区别,是一样的。
  • 限制所有tcp端口iptables -A INPUT -p tcp -m state --state NEW,UNTRACKED -j DROP
  • 为了方便维护/修改,可以创建一个自定义chain,然后把上面的规则都写入到这个自定义chain中。
    需要修改时,iptables -F port_limit直接清空这个chain的内容,重新添加规则。
    iptables -t filter -N port_limit         #自定义chain
    iptables -t filter -I INPUT -j port_limit   #插入INPUT表中,第一条
    
  • 限制nat转发端口
    在 FORWARD 中限制。
    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
    
    或在 nat 的 PREROUTING 中限制。
  • 在 filter 的 INPUT 中,对nat端口是无效的。
    因为数据包被prerouting 处理后(目标非本地的包)转向了 forward表,不经过input表。

nft 命令行 ipv4

  • 限制本机的端口
    具体的插入位置,用nft list ruleset查看,自己机器中已有的 nft chain,找到 filter hook input 的 chain。
    没有的话,自己创建一个chain。
    在我机器上,在 table ip filter { chain INPUT { type filter hook input priority 0; } }
    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
    
  • 限制所有tcp端口nft add rule ip filter INPUT meta l4proto tcp ct state { new, untracked } counter reject
  • 为了方便维护/修改,可以创建一个自定义chain,然后把上面的规则都写入到这个自定义chain中。
    需要修改时,nft flush chain ip filter port_limit直接清空这个chain的内容,重新添加规则。
    nft add chain ip filter port_limit        #自定义chain
    nft insert rule ip filter INPUT jump port_limit   #插入INPUT表中,第一条
    
  • 限制nat转发端口
    类似,找到 filter hook forward 的 chain,写入转发规则限制即可。
    没有的话,自己创建一个chain。
    在我机器上,在 table ip filter { chain FORWARD { type filter hook forward priority 0; } }
    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
    

nft 本地端口重定向

  • 需要nat hook prerouting的chain,通常没有,自己创建一个chain。
    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
    
    如果要限制来源ip,在input chain中限制 22口就可以了。目的地,为本机的数据包,是要经过 input表的,到达input表时,目标端口已经是 22。
  • iptables
    iptables -t nat -A PREROUTING -p tcp --dport 1234 -j REDIRECT --to-port 22
    

OpenWRT 在 fw4 中使用 ipset 匹配来源 IP

  • op-22 使用的是 fw4,即 nft。
    op-21 以及之前的版本用的是 fw3,即 iptables。
  • op-22.03.03,luci-app-firewall - git-23.035.45612
    web luci页面,无法配置 ipset,也无法把 ipset 配置到规则中使用。
    只能手工编辑 firewall 配置文件,或者使用 "uci" 命令配置。
  • 升级luci-app-firewall到最新,web luci 就有 ipset的配置
    用命令升级,opkg upgrade luci-app-firewall
    • luci-app-firewall - git-23.089.66165
      luci-app-firewall - git-23.093.42704(目前最新的版本)。
      web luci页面就可以配置 ipset。IP列表文件 上传到 /etc/luci-uploads/目录中。
      ipset 配置中,Packet Field Match只能选取一个,不能填写 comment,否则出错。
      不支持 iprange。
      规则配置中,高级设置,有"Use ipset"的选项
  • 无论 web luci是否支持 ipset配置,手工设置总是 有效的
  • fw4 下,使用 ipset。【官方文档 IP sets】,【官方例子 fw3_config_ipset
    以下是针对luci-app-firewall - git-23.035.45612,web luci无 ipset配置。
    使用 手工编辑 firewall 配置文件,或者使用 "uci" 命令配置。
    • /etc/config/firewall 添加以下配置行。
      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'
      
      net_list.txt 文件如下,
      # 支持 空行,支持 注释。 空行和注释会被忽略
      10.12.45.0/24
      10.34.56.78
      10.45.67.0/24
      
      "list entry" 和 "option loadfile" 可以混用。结果是它们的"合集"
      用命令fw4 check检查无错误。用命令fw4 restart重启防火墙。
    • "match" 是 "net",支持网段/IP。会在table inet fw4 { }中生成一个集合 set,
      set main_allowed { type ipv4_addr; flags interval; auto-merge; }
    • "match" 是 "ip",仅支持IP,写网段也会 识别为 IP。生成的集合 set,
      则是 set main_allowed { type ipv4_addr; }
    • option maxelem '0' 正常 不设置,默认值是 0,添加的条目没限制。似乎也不会预分配内存,没见到内存空间占用变大。
      如果设置,会限制添加条目的数量,似乎还会预分配内存。如果设置 65536,会见到内存占用升高。(2023-04测试,op22.03.3, luci-app-firewall git-23.035)
      如果某个 rule 会动态添加条目到这个 ipset,就必须设置,限制一下数量,防止条目太多而内存溢出。
    • uci 的例子。
      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
      
    • /etc/config/firewall 中,找到需要匹配来源 IP 的 rule
      删除这个 rule中 所有的list src_ip ...
      加入一行option ipset 'main_allowed src'
      例子如下,
      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 '*'
      
      重启防火墙生效。/etc/init.d/firewall restartfw4 restart
      • 如果list src_ip ...option ipset混用,结果是要满足两种配置的"交集"才能访问。
    • 手工配置好 ipset 之后。在 web luci 中也见不到这个 ipset。(2023-04测试,op22.03.3, luci-app-firewall git-23.035)
    • 上面的这个"web-server"规则。在 web luci 的 "Traffic Rules" 中,能见到这个 rule,但见不到 ipset的设置。
      在 web luci 中修改这个"web-server"规则,不会丢失option ipset的配置。(2023-04测试,op22.03.3, luci-app-firewall git-23.035)
      添加 "source address" 等于添加 list src_ip '4.3.2.0/24',会导致实际的来源 IP,必须匹配 两种配置的"交集"
      因为rule是这样的ip saddr { 4.3.2.0/24 } tcp dport { 80, 443 } ip saddr @main_allowed counter accept
      清空 "source address",不丢失option ipset的配置,规则还是最初的效果。
  • fw4 还支持 config include 添加自定义 rule。
    见【官方文档 includes_for_2203_and_later_with_fw4】。
  • fw4 的 web luci 界面,配置 ipset 不支持 iprange,(目前最新是 luci-app-firewall git-23.093)。
    而 "match" 是 "net" 时,生成集合 set 是包含 "flags interval",即支持iprange。
    可以通过以下两种办法(二选一),添加 ipset 的 element,使用iprange。
    假设你在 web luci 中,添加一个 ipset,名称是 "main_allowed"。
    • 或,创建文件 /usr/share/nftables.d/ruleset-post/add-element.nft,如果对应目录不存在,则自己创建目录。
      # file: add-element.nft
      add element inet fw4 main_allowed { 10.12.45.100-10.12.45.200}
      
    • 或,在 /etc/config/firewall 中添加,
      config include
          option enabled 1
          option type 'script'
          option path '/etc/add-ipset-element.sh'
          option fw4_compatible 1
      
      #!/bin/sh
      # file: add-ipset-element.sh
      nft add element inet fw4 main_allowed { 10.12.45.100-10.12.45.200}
      

PVE 的防火墙配置

禁止某ip访问特定端口

  • 并统计数据包:
    nft add rule inet filter input ip saddr 170.64.134.97 tcp dport 22 counter drop

限制sshd的登录

----end----


转载注明来源: 本文链接 https://www.cnblogs.com/osnosn/p/16320603.html
来自 osnosn的博客 https://www.cnblogs.com/osnosn/ .


posted on 2022-05-28 17:57  osnosn  阅读(2270)  评论(0编辑  收藏  举报