Part2——nftables基础防护配置

这里有两台机子,因此nftables的配置需要根据不同的机子分别来配。

第一台是运行mc服务端的机器,这里统一称为MC机,为了保证性能需求,这台机子上只部署一个MCSManager面板+节点,因此MC机默认将需要额外暴露三个端口:

  • 23333——MCSManager的网页后台
  • 24444——MCSManager可用的节点
  • 25565——默认的MC服务器udp连接用端口

然后第二台是给MC机以上端口配反代和跳板的机器,这里统一称为跳板机,这台机子上需要部署的是docker和NPM,因为需要nginx,自然跳板机将需要暴露80、443端口。接下来分别配置这两台机器的nftables防火墙。

MC机:

首先明确需求,在MC机上我们将使用nftables禁止任何人通过ip:port的方式访问2333324444端口,仅允许跳板机的NPM/白名单ip访问这两个端口,从而将MCSManager给藏起来。

对于25565端口,也就是连接mc游戏服务器用的udp端口,有下面几种处理方法,能单独用也能一起用:

  • 像更换ssh端口一样更换25565端口
  • 只允许通过跳板机/白名单ip来访问MC机的25565端口
  • 使用cf的srv来访问MC机/跳板机

这里采用的处理组合是:

  • 不更换MC机设置的25565端口,但是nftables设置25565端口仅允许跳板机/白名单ip访问
  • 使用跳板机的NPM将MC机的25565端口转发到跳板机的25555端口
  • 最后,使用cf的srv记录来访问跳板机的25555端口

其实我也不知道要防什么东西,私人服务器搞这么复杂的处理其实会显得有点多余,不过这样做能够最大程度的保护你的MC机的ip不被泄露(对的只是MC机,跳板机还是需要暴露的只不过不是裸体这样子),另外按照我的理解,srv还能通过调整权重来达到多跳板机分流/均衡负载的效果,不过这些都有点偏题,这里就不详细展开了。

跳板机:

根据MC机的配置,很明显我们需要开放25555端口,另外由于反代用的NPM是部署在跳板机上的,因此80、443端口也需要开放,关于Docker和NPM的部署可以参照部署komga的另外一篇博文,这里的NPM的部署方式跟那篇博文是一模一样的。

以上是基础概念,接下来进入实战,为了防止配置冲突导致额外问题,请事先确认自己的系统使用的是nftables而不是iptables,iptables跟ufw需要提前卸载。

MC机nftables详细配置:

MC机上的服务比较单一,我们使用单个配置文件解决。debian12默认的nftables配置文件在/etc/nftables.conf,使用nano /etc/nftables.conf打开:

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
    chain input {
        type filter hook input priority 0;

        # 允许来自环回接口的流量
        iifname "lo" accept

        # 允许已建立的连接和相关的连接
        ct state {established, related} accept

        # 允许来自 跳板机/NPM 1.2.3.4 的所有流量(白名单ip也可以加在这里)
        ip saddr 1.2.3.4 accept

        # 选择性是否开放 25565 端口 (TCP 和 UDP),开放就取消下面两行的注释
        # tcp dport 25565 accept
        # udp dport 25565 accept

        # 允许有限的 ICMP (ping) 流量,并限制 ping 的速率
        icmp type echo-request limit rate 5/second accept
        icmp type echo-request drop
        icmpv6 type echo-request limit rate 5/second accept
        icmpv6 type echo-request drop 

        # 允许 SSH (确保更改端口号),限制速率,记录被drop的扫狗SSH连接
        ip daddr 1.2.3.5(替换成你MC机的ip) tcp dport 12345(之前修改的ssh端口号) ct state new limit rate 10/minute accept comment "IPv4 SSH"
        ip daddr 1.2.3.5(替换成你MC机的ip) tcp dport 12345(之前修改的ssh端口号) log prefix "SSH IPv4 Dropped: " drop

        # 阻止 23333, 24444 端口直连
        tcp dport {23333, 24444} drop

        # 默认策略:丢弃所有其他流量
        drop
    }

    chain forward {
        type filter hook forward priority 0;
        drop
    }

    chain output {
        type filter hook output priority 0;
        accept
    }
}

保存退出,应用配置:

sudo nft -f /etc/nftables.conf

应用完成后,尝试使用白名单之外的ip,如果没设置白名单那就是任意ip尝试访问MC机的ip:23333/24444看看是不是无法访问,如果无法访问就证明MC机上的nftables配置已经正常生效。

跳板机nftables详细配置:

跳板机上的服务比较多样,像MC机一样使用单一的nftables.conf配置文件会显得很乱,所以我们来使用模块化配置方法,以下部分内容是从Protect Your Incus Server with NFtables学来的,我让gpt分析了一下他的nftables配置,评价是“十分健壮”,因此选择基于他的配置来修改。

模块化nftables配置结构:

/etc/nftables.conf              # 主配置文件
/etc/nftables.d/                # 模块化规则目录
├── vars.conf                   # 变量定义
├── base-fw.nft                 # 基础防火墙规则
└── ssh.nft                     # ssh专用规则

还是那句,为了防止配置冲突导致额外问题,请事先确认自己的系统使用的是nftables而不是iptables,iptables跟ufw需要提前卸载。

因为这台机子上有使用Docker部署的NPM,因此会有docker0跟npm容器的br网桥,先执行ip a记下两个网桥的名字,一般是就叫docker0br-一串乱码

首先备份原来的nftables.conf

cp /etc/nftables.conf /etc/nftables.conf_orig_bu

创建nftables.d文件夹:

mkdir -p /etc/nftables.d

创建新的nftables.conf文件,nano /etc/nftables.conf

#!/usr/sbin/nft -f

flush ruleset

# Include the variables file only once
include "/etc/nftables.d/vars.conf"

# Include all other configuration files
include "/etc/nftables.d/*.nft"

可以看见这里的结构很简单,可以把它当作只是一个入口而已,详细的变量和规则都在nftables.d文件夹里面配置。

入口搞定,接下来是/etc/nftables.d/vars.conf

#!/usr/sbin/nft -f

# Define interfaces
# 你的wan网卡可能未必叫"eth0",请用ip a检查
define WAN = "eth0"
define DOCKER = "docker0"
define BRIDGE = "br-一串乱码"

# Host IP addresses for the WAN interface
define IPV4 = "跳板机的ipv4地址"  # Replace with your IPv4 address
define IPV6 = "跳板机的ipv6地址"  # Replace with your IPv6 address

# SSH port for secure management
define SSH_PORT = 12345

然后是/etc/nftables.d/base-fw.nft

#!/usr/sbin/nft -f

table inet filter {
    # Define allowed ICMP types
    set icmp_allowed_types {
        type icmp_type
        elements = { destination-unreachable, time-exceeded, parameter-problem }
    }

    set icmpv6_allowed_types {
        type icmpv6_type
        elements = { destination-unreachable, packet-too-big, time-exceeded, parameter-problem,
                     nd-router-advert, nd-neighbor-advert, nd-router-solicit, nd-neighbor-solicit }
    }

    # IPv4 inbound chain
    chain inbound_ipv4 {
        icmp type @icmp_allowed_types accept
        icmp type echo-request limit rate 5/second accept
    }

    # IPv6 inbound chain
    chain inbound_ipv6 {
        icmpv6 type @icmpv6_allowed_types accept
        icmpv6 type echo-request limit rate 5/second accept
    }

    # Main inbound chain
    chain inbound {
        type filter hook input priority 0; policy drop;

        # Connection tracking
        ct state vmap { established : accept, related : accept, invalid : drop }

        # Allow loopback
        iifname lo accept

        # mailx
        ip daddr 127.0.0.1 tcp dport 25 accept

        # Route IPv4/IPv6 traffic
        meta protocol vmap { ip : jump inbound_ipv4, ip6 : jump inbound_ipv6 }

        # Docker
        iifname $DOCKER tcp dport { 80, 443, 25555 } accept
        iifname $BRIDGE tcp dport { 80, 443, 25555 } accept
        iifname $DOCKER udp dport { 80, 443, 25555 } accept
        iifname $BRIDGE udp dport { 80, 443, 25555 } accept

        # TCP security measures
        tcp flags & (fin|syn|rst|ack) != syn ct state new drop
        tcp flags & (fin|syn|rst|psh|ack|urg) == fin|syn|rst|psh|ack|urg drop
        tcp flags & (fin|syn|rst|psh|ack|urg) == 0x0 counter drop

        # Logging
        log prefix "DROP IN: " level info

        # Drop fragments
        ip frag-off & 0x1fff != 0 drop
    }

    # Forward chain
    chain forward {
        type filter hook forward priority 0; policy drop;

        ct state established,related accept

        # Docker
        iifname $BRIDGE oifname $WAN accept
        iifname $WAN oifname $BRIDGE ct state new accept

        log prefix "DROP FORWARD: " level info
    }

    # Outgoing chain
    chain outgoing {
        type filter hook output priority 0; policy accept;
    }
}

最后是/etc/nftables.d/ssh.nft

#!/usr/sbin/nft -f

table inet filter {
    chain inbound {
        # Allow SSH access
        ip daddr $IPV4 tcp dport $SSH_PORT ct state new limit rate 10/minute accept comment "IPv4 SSH"
        ip6 daddr $IPV6 tcp dport $SSH_PORT ct state new limit rate 10/minute accept comment "IPv6 SSH"

        # Log and drop excessive SSH attempts
        ip daddr $IPV4 tcp dport $SSH_PORT log prefix "SSH IPv4 Dropped: " drop
        ip6 daddr $IPV6 tcp dport $SSH_PORT log prefix "SSH IPv6 Dropped: " drop
    }
}

应用配置:

sudo nft -f /etc/nftables.conf

检查已启用的nftables规则:

sudo nft list ruleset

注意,每次使用sudo nft -f /etc/nftables.conf,或者准确来说是每次执行过nftables.conf里的flush ruleset之后,Docker使用的iptables-nft兼容规则都会被清除掉,这意味着这个时候你是无法访问NPM/反代好的MCSManager面板的,每次执行完sudo nft -f /etc/nftables.conf/flush ruleset后,你需要手动重启一次docker:

# 重启docker命令二选一执行

service docker restart
systemctl restart docker

到这里,基于nftables防火墙和fail2ban的服务器基础防护就算是做完了。

页: 1 2 3 4 5