Discourse 설치 보안을 위한 Nftables 규칙

@OrkoGrayskull 감사합니다!

/etc/docker/daemon.json에서 firewall-backendnftables로 설정할 수 있게 되었고, 지금 Debian Trixie 또는 Bookworm을 사용 중이시라면 이 문제에 대한 업데이트가 있을까요? 저도 이 설정을 시험해 보고 있습니다…

/etc/sysctl.conf에서 net.ipv4.ip_forward=1을 설정해야 한다는 것을 발견했습니다.

Docker with nftables 문서에는 다음과 같이 나와 있습니다:

Docker의 테이블을 직접 수정하지 마십시오. 수정 내용이 손실될 가능성이 높으며, Docker는 자신의 테이블에 대한 완전한 소유권을 유지하기를 기대합니다.

그래서 저는 Docker 규칙을 건드리지 않는 것이 좋기를 바라고 있습니다…

현재 제 설정은 다음과 같습니다. 일부 규칙은 Ansible을 통해 추가했습니다(이 서버는 Postfix를 사용하여 SMTP를 Discourse로 전달하기 때문에 포트 25가 필요합니다):

table inet ansible_firewall {
        chain inbound_ipv4 {
                icmp type echo-request limit rate 5/second accept comment "Accept IPv4 rate limited ICMP pings"
        }

        chain inbound_ipv6 {
                icmpv6 type { nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert } accept comment "Accept IPv6 neighbour discovery"
                icmpv6 type echo-request limit rate 5/second accept comment "Accept IPv6 rate limited ICMP pings"
        }

        chain inbound {
                type filter hook input priority filter; policy drop;
                ct state vmap { invalid : drop, established : accept, related : accept } comment "Allow traffic from established and related packets, drop invalid"
                iifname "lo" accept comment "Allow loopback traffic"
                meta protocol vmap { ip : jump inbound_ipv4, ip6 : jump inbound_ipv6 } comment "Jump to chain according to layer 3 protocol using a verdict map"
                tcp dport 22 accept comment "Allow SSH on port TCP/22"
                tcp dport { 80, 443 } accept comment "Allow HTTP on port TCP/80 and HTTPS on port TCP/443"
        }

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

        chain output {
                type filter hook output priority filter; policy accept;
                oifname "lo" accept comment "Allow outgoing from loopback interface"
        }
}

그리고 Docker / Discourse의 규칙은 다음과 같습니다(참고: 이 서버에는 IPv6 주소가 없습니다):

table ip docker-bridges {
        map filter-forward-in-jumps {
                type ifname : verdict
                elements = { "docker0" : jump filter-forward-in__docker0 }
        }

        map filter-forward-out-jumps {
                type ifname : verdict
                elements = { "docker0" : jump filter-forward-out__docker0 }
        }

        map nat-postrouting-in-jumps {
                type ifname : verdict
                elements = { "docker0" : jump nat-postrouting-in__docker0 }
        }

        map nat-postrouting-out-jumps {
                type ifname : verdict
                elements = { "docker0" : jump nat-postrouting-out__docker0 }
        }

        chain filter-FORWARD {
                type filter hook forward priority filter; policy accept;
                oifname vmap @filter-forward-in-jumps
                iifname vmap @filter-forward-out-jumps
        }

        chain nat-OUTPUT {
                type nat hook output priority -100; policy accept;
                ip daddr != 127.0.0.0/8 fib daddr type local counter jump nat-prerouting-and-output
        }

        chain nat-POSTROUTING {
                type nat hook postrouting priority srcnat; policy accept;
                iifname vmap @nat-postrouting-out-jumps
                oifname vmap @nat-postrouting-in-jumps
        }

        chain nat-PREROUTING {
                type nat hook prerouting priority dstnat; policy accept;
                fib daddr type local counter jump nat-prerouting-and-output
        }

        chain nat-prerouting-and-output {
                iifname != "docker0" tcp dport 80 counter dnat to 172.17.0.2:80 comment "DNAT"
                iifname != "docker0" tcp dport 443 counter dnat to 172.17.0.2:443 comment "DNAT"
        }

        chain raw-PREROUTING {
                type filter hook prerouting priority raw; policy accept;
                ip daddr 172.17.0.2 iifname != "docker0" counter drop comment "DROP DIRECT ACCESS"
        }

        chain filter-forward-in__docker0 {
                ct state established,related counter accept
                iifname "docker0" counter accept comment "ICC"
                ip daddr 172.17.0.2 tcp dport 80 counter accept
                ip daddr 172.17.0.2 tcp dport 443 counter accept
                counter drop comment "UNPUBLISHED PORT DROP"
        }

        chain filter-forward-out__docker0 {
                ct state established,related counter accept
                counter accept comment "OUTGOING"
        }

        chain nat-postrouting-in__docker0 {
        }

        chain nat-postrouting-out__docker0 {
                oifname != "docker0" ip saddr 172.17.0.0/16 counter masquerade comment "MASQUERADE"
        }
}
table ip6 docker-bridges {
        map filter-forward-in-jumps {
                type ifname : verdict
        }

        map filter-forward-out-jumps {
                type ifname : verdict
        }

        map nat-postrouting-in-jumps {
                type ifname : verdict
        }

        map nat-postrouting-out-jumps {
                type ifname : verdict
        }

        chain filter-FORWARD {
                type filter hook forward priority filter; policy accept;
                oifname vmap @filter-forward-in-jumps
                iifname vmap @filter-forward-out-jumps
        }

        chain nat-OUTPUT {
                type nat hook output priority -100; policy accept;
                ip6 daddr != ::1 fib daddr type local counter jump nat-prerouting-and-output
        }

        chain nat-POSTROUTING {
                type nat hook postrouting priority srcnat; policy accept;
                iifname vmap @nat-postrouting-out-jumps
                oifname vmap @nat-postrouting-in-jumps
        }

        chain nat-PREROUTING {
                type nat hook prerouting priority dstnat; policy accept;
                fib daddr type local counter jump nat-prerouting-and-output
        }

        chain nat-prerouting-and-output {
        }

        chain raw-PREROUTING {
                type filter hook prerouting priority raw; policy accept;
        }
}

포트 80과 443을 제외한 모든 것은 문제가 없는 것 같습니다… :roll_eyes: