해결이 필요한 문제

해결이 필요한 문제

내 컴퓨터에는 매우 엄격한 nftables 구성이 활성화된 두 개의 Docker 컨테이너가 실행되고 있습니다. 이 방식을 유지하고 싶지만 도커 컨테이너에 대한 외부 액세스를 허용 목록에 추가합니다.

컨테이너는 포트 80과 6200을 엽니다. docker 서비스는 iptables가 비활성화된 상태로 시작됩니다.

다음은 내 시도를 포함한 현재 방화벽 구성입니다. icmp, ssh및 은(는 http) https이미 열려 있습니다. Docker의 경우 http 포트 80과 애플리케이션별 포트 6200만 필요합니다. 나는 192.168.0.0/16가능한 한 제한적 으로 Docker에 대한 액세스만 허용하려고 노력합니다 .

 table inet filter {
    chain input {
            type filter hook input priority 0; policy drop;
            iif lo accept
            iif eno2 icmp type echo-request accept
            iif eno2 ip 192.168.0.0/16 tcp dport 22 accept
            iif eno2 ip 192.168.0.0/16 tcp dport { http, https, 6200 } accept
    }

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

    chain output {
            type filter hook output priority 0; policy drop;
    }
}

docker0인터페이스에 추가 규칙을 추가하려고 시도했지만 성공하지 못했습니다. 수정해야 할 것 같나요 chain forward?

답변1

질문이 간단해 보일 수도 있지만, 그렇습니다. Docker가 있으면 네트워킹을 처리하는 시스템의 다른 부분에 항상 몇 가지 문제가 발생합니다. 한 번nftables특히 Docker가 중단된 후에는 Docker의 광범위한 채택과 직접 사용으로 인해 br_netfilter상황이 더 단순해질 수 있습니다 .

아직 사용할 가치가 있다고 생각하신다면nftablesDocker의 라인을 따라 Docker가 해당 부분을 처리하도록 하고 간단한 변경(예: 새 방화벽을 시작하는 등)만 수행되는 한 다른 방화벽 규칙에서 Docker 설정을 중복할 필요가 없도록 하는 접근 방식을 아래에서 생각해 냈습니다. 새로운 노출된 포트가 있는 컨테이너).

해결이 필요한 문제

iptables아직도 필요하다

현재(2021년) Docker를 계속 사용하고 있습니다.iptables그리고 오직iptables(당신은 또한 사용할 수 있습니다방화벽하지만 오직방화벽그리고iptables뒤쪽 끝. 어쨌든 나는 이 시나리오를 고려하지 않을 것이다). 따라서 현재로서는 순수한 것을 얻을 수 있는 방법이 없습니다.nftablesDocker를 사용할 때의 시스템. 사실은iptables그럴 수도 iptables-legacy있고 iptables-nft상관없어요.

다음은 관련 발췌문입니다.도커와 iptables이 경우에 유용합니다:

Docker는 iptables다음과 같은 두 개의 사용자 지정 체인을 설치합니다.DOCKER-USERDOCKER들어오는 패킷이 항상 이 두 체인에 의해 먼저 확인되도록 합니다.

Docker의 모든 iptables 규칙이 DOCKER체인 에 추가됩니다.. 이 체인을 수동으로 작동하지 마십시오.Docker 규칙보다 먼저 로드되는 규칙을 추가해야 하는 경우 DOCKER-USER체인 에 추가하세요.. 이러한 규칙은 Docker가 자동으로 규칙을 생성하기 전에 적용됩니다.

Nitpicking: 실제로 Docker는 이 작업을 수행하므로 -A DOCKER-USER -j RETURNdocker를 시작하기 전에 규칙을 추가해야 합니다. 또는 더 나은 방법은 다음과 같습니다.끼워 넣다모든 경우에 유효합니다.

FORWARD체인 에 규칙이 추가됩니다.-- 수동으로 또는 다른 iptables 기반 방화벽을 통해 --평가를 받다뒤쪽에이 사슬.

Docker는 또한 체인의 정책을 FORWARD로 설정합니다 DROP. Docker 호스트가 라우터 역할도 하는 경우 해당 라우터는 더 이상 트래픽을 전달하지 않습니다.

Docker는 IP 전달을 활성화하지만 기본적으로 Docker 자체가 아닌 다른 목적으로 방화벽과 함께 사용합니다.

iptablesDocker 엔진의 구성 파일에서 키를 false로 설정할 수 있지만 /etc/docker/daemon.json이 옵션은 대부분의 사용자에게 적합하지 않습니다.Docker가 iptables 규칙을 생성하는 것을 완전히 방지하는 것은 불가능합니다., 사실 이후에 생성하는 것은 복잡하고 이 지침의 범위를 벗어납니다. iptables를 false로 설정하면 Docker 엔진의 컨테이너 네트워크가 손상될 수 있습니다..

갖는 것을 피할 수 없다iptables.

br_netfilter

그리고,Docker는 커널 모듈도 로드합니다.br_netfilter이 속성을 설정하려면:

# sysctl net.bridge.bridge-nf-call-iptables
net.bridge.bridge-nf-call-iptables = 1

그래서브리지된프레임(여기서는 IPv4 유형액자임시로 IPv4로 변환데이터 팩) 필터링됨iptables 그리고통과nftables(명시적으로 문서화되어 있지는 않지만,nftables좋다iptablesNetfilter에 연결하면 Netfilter는 후크의 출처에 관계없이 이러한 후크를 호출합니다.iptables또는nftables).

이 기능은 Docker와 상호 작용할 때 문제의 주요 원인입니다. 이것을 이해하지 못하면 왜 컨테이너가 동일한 내부 브리지 LAN에 있는지 궁금해 할 것입니다.서로 의사소통이 불가능하다더 이상 Docker 또는 Docker가 실행하는 다른 항목(LXC, libvirt/QEMU...)에 의해 처리되지 않습니다.

이것은일반 네트워크의 Netfilter 및 패킷 흐름:

일반 네트워크의 Netfilter 및 패킷 흐름

단일 가닥iptables또는nftables따라서 IP/INET 제품군은 일반적인 라우팅 경로(녹색 네트워크 계층 필드 내의 녹색 상자)와 브리지 경로(파란색 링크 계층 필드 내의 녹색 상자)라는 두 가지 다른 방법으로 탐색할 수 있습니다. 이것문서또한 다음과 같이 말했습니다.

브리지된 패킷은 레이어 1(링크 레이어) 위의 네트워크 코드에 절대 들어가지 않습니다. 따라서 브리지된 IP 패킷/프레임에는 IP 코드가 입력되지 않습니다.

이는 데이터 패킷이 통과하지 않도록 보장합니다.두 배같은 체인이 안심입니다.

사이의 상호 작용iptables그리고nftables

사용하는 것이 목표이기 때문에nftables함께 사용하는 방법을 알아야합니다.

이 질문에 대한 나의 대답은 다음과 같습니다.

결론적으로:

  • iptables그리고nftables함께 사용할 수 있습니다
  • nftables결정론적인 평가 순서를 갖도록 우선순위를 지정할 수 있습니다.iptables그리고nftables(이 예의 경우:nftables뒤쪽에iptables)
  • 이런 일이 발생할 때마다 언제 어디서나 삭제된 패킷은 명시적으로 삭제된 상태로 유지됩니다.
  • 허용된 패킷(다음으로 표시됩니다.iptables) 동일한 후크의 다음 체인에서 평가를 계속합니다.nftables'체인).
  • 패킷 표시를 사용하여 서로 간에 메시지를 전송할 수 있습니다.iptables그리고nftables

이 문제를 일반적인 방법으로 해결하는 방법

교량 경로 처리

nftablesip/inet 계열의 규칙에서는 이 작업을 피해야 합니다.아무것다리 경로에서. Docker 활성화가 없으면 br_netfilter이 문제를 전혀 고려할 필요가 없습니다. ip/inet 제품군의 브리지 경로에 있는지 여부를 감지하는 것은 다음 작업에 맡겨야 합니다.iptables갖지 않기 위해nftables이를 처리하고 Docker 설치 여부에 관계없이 보편적인 상태를 유지합니다. 하기도 더 쉽구요iptables비교nftablesip/inet 제품군에는 특정 항목이 있으므로iptables -m physdev --physdev-is-bridged시험:

[!] --physdev-is-bridged

패킷이 브리지되는 경우 일치합니다.따라서 라우팅되지 않습니다. 이는 FORWARD 및 POSTROUTING 체인에서만 유용합니다.

br_netfilter이 일치는 아직 수행되지 않은 경우 Docker에 따라 달라지며 로드됩니다. br_netfilter!로 인한 문제를 해결해야 합니다!br_netfilter

태그를 사용하여 연결iptables그리고nftables

아이디어는 태그를 사용하여 메시지를 얻는 것입니다.iptables패스nftables, 상황을 구별하십시오:

  • 규칙 평가는 라우팅 경로가 아닌 브리지 경로에서 발생합니다.

    언제나수용하다그런 상황.

  • Docker가 패킷을 승인했습니다.

    더 많은 제한사항을 추가할 수 있지만 대부분의 경우수용하다그런 상황.

  • Docker가 패킷을 무시함

    정상적인 사용nftablesDocker의 규칙에 대해 걱정하지 마십시오.

  • 어떤 이유로든 패킷이 삭제되었습니다.iptables

    의미없는 사건이네요nftables이 패킷은 표시되지 않으며 이에 대해 수행할 필요나 가능한 조치가 없습니다.

iptables

Docker가 시작되기 전에 완료한 경우 필터 체인을 만듭니다 DOCKER-USER.

iptables -N DOCKER-USER

나중에 완료되면 Docker가 이를 생성합니다.

체인에서 Docker 평가 전에 브리지 경로 감지 사례에 포함된 패킷을 DOCKER다른 표시로 표시하는 규칙을 추가합니다(이전과 같이 여기에 삽입하되 여기서 중요한 자연 순서를 유지하기 위해 번호를 매깁니다).

iptables -I DOCKER-USER 1 -j MARK --set-mark 0xd0cca5e
iptables -I DOCKER-USER 2 -m physdev --physdev-is-bridged -j MARK --set-mark 0x10ca1

0x10ca1 및 0xd0cca5e는 임의로 선택된 값입니다.

DOCKER임시 Docker 평가 태그인 경우에만 패킷의 태그를 재설정하는 최종 규칙을 추가합니다(Docker 실행 전이나 후에 Docker는 항상 체인을 삽입하기 전에 삽입하므로 효과는 동일함 ).그리고ACCEPT덮어쓸 마지막 항목을 추가하세요.Docker의 기본 DROP정책 설정 FORWARD은 체인에 있습니다.:추가 평가를 미루자는 생각입니다.nftablesDocker 독립적 패킷에 사용됩니다.

iptables -A FORWARD -m mark --mark 0xd0cca5e -j MARK --set-mark 0
iptables -A FORWARD -j ACCEPT

nftables

우선순위 값을 inet filter forward다음보다 약간 큰 값으로 변경합니다.NF_IP_PRI_FILTER(0)(예: 10)nftables순방향 체인iptables filter/FORWARD이 연대기를 존중합니다. OP 규칙 세트의 기본 링크 줄은 다음과 같이 변경되어야 합니다.

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

도착하다:

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

이전에 설명한 4가지 조건은 다음 위치에서 감지될 수 있습니다.nftables포장의 표시를 확인하여. 디버깅을 돕기 위해 표현식을 추가합니다 counter.

  • 태그 0x10ca1: 브리지 경로

    브리지 경로 투명 전송 규칙을 추가합니다.

    nft add rule inet filter forward meta mark 0x10ca1 counter accept
    
  • 태그 0xd0cca5e: Docker 케이스

    • Docker 사례를 처리하기 위한 일반/사용자 체인을 생성하고 이를 호출하는 규칙을 추가합니다.

      nft add chain inet filter dockercase
      nft add rule inet filter forward meta mark 0xd0cca5e counter jump dockercase
      
    • Docker에 관한 추가 제한 사항을 추가하되 기본적으로 허용합니다.

      예를 들어 다음에서 들어오는 패킷을 제한합니다.이노 2인터페이스는 192.168.0.0/16 내의 개인 주소에서 오는 경우에만 허용됩니다.

      nft add rule inet filter dockercase iif eno2 ip saddr != 192.168.0.0/16 counter drop
      nft add rule inet filter dockercase counter accept
      
  • 태그 없음: Docker와 관련이 없는 일반적인 경우

    아무것도 포함하지 않고 기본값을 갖는 것을 포함하여 Docker의 존재를 고려하지 않고 수행할 수 있는 작업을 추가합니다.줄이다그렇지 않으면 평소부터 시작될 수 있습니다.ct state related,established accept

  • (패킷 없음: 삭제됨iptables, 대소문자 없음)

위의 예는 다음과 같습니다.

...
    chain forward {
        type filter hook forward priority 10; policy drop;
        meta mark 0x10ca1 counter accept
        meta mark 0xd0cca5e counter jump dockercase
    }

    chain dockercase {
        iif eno2 ip saddr != 192.168.0.0/16 counter drop
        counter accept
    }
...

범용 처리 구현

포트 80 및 6200은nftables더 이상 규칙이 없습니다. Docker 명령을 사용하여 새 포트를 노출해야 하는 새 컨테이너를 추가하는 경우에는 아무 것도 할 필요가 없습니다.nftables: 태깅으로 인해 처리가 완료되었습니다.

더 많은 체인 추가

아니면br_netfilter영향, 다른 근거가 있어야 할까요?nftables속성에 연결하거나 hook forward삭제 hook postrouting규칙을 포함하거나 더 유용하게는 다음에 설명된 트릭을 사용하지 않고 규칙을 변경합니다(당연히...).이전 링크는 그림 7b 아래에 있습니다., 동일한 배열이 이루어져야 합니다.

  • 우선순위 값은 다음보다 높아야 합니다.iptables'동등한 체인 우선순위

  • 그런iptables등가 체인( filter/FORWARD에서 이미 수행되지 않은 경우 DOCKER-USER)은 다음을 수신해야 합니다.

    iptables -t foo -I BAR -m physdev --physdev-is-bridged -j MARK --set-mark 0x10ca1

    경우에 따라 , 사이 , 또는 foo사이 및 사이rawmanglenatBARPREROUTINGPOSTROUTING

  • 그리고 첫 번째 규칙nftables체인은 다시 다음과 같아야 합니다.

    meta mark 0x10ca1 accept
    
  • 체인의 정책이 다시 그렇다면 drop이전과 마찬가지로 0xd0cca5e로 표시된 규칙을 사용하여 사용자/일반 체인 점프를 다시 포함해야 합니다.

이에 대해 hook prerouting문서에는 --physdev-is-bridged이것이 적용되지 않을 수 있다고 나와 있습니다 PREROUTING. 절대 기본 삭제 정책을 사용하지 마십시오. 어쨌든, hook prerouting경우에 따라 아직 0xd0cca5e태그를 상속받을 수 없지만 filter/FORWARD다음을 사용할 때도 마찬가지입니다.iptables: PREROUTING 미래에 무슨 일이 일어날지 예측할 수 있는 방법이 없습니다.

브리지 수준에서 정말로 뭔가를 하고 싶다면 다음을 사용하세요.nftables브리지 계열에서는 브리지 경로에서 호출되는 ip/inet 계열의 특별한 경우에 의존하지 마십시오 br_netfilter.

경고하다

이제 이 문제를 처리하기 위해 마커를 사용하는 동시에 다른 문제를 처리하기 위해 마커를 사용하는 것이 더 어렵지만 조금만 주의하면 불가능하지는 않습니다. 예를 들어 이러한 태그와 함께 비트 연산 및 마스크를 사용합니다. 이 작업은 다음에서 수행할 수 있습니다.iptables그리고nftables. ip rule마커를 선택기로 사용하는 경우에도 마스크가 허용됩니다.


중요한 추가 필수 조정

도커 추가iptables를 사용한 포트 전달 규칙'DNAT표적. 마지막으로 노출된/게시된 모든 포트는라우팅됨호스트가 수신하지 않고 컨테이너에 전달합니다. 이는 그들이 다음을 사용할 것임을 의미합니다.iptables체인 filter/FORWARD도 마찬가지입니다 (OP의 규칙 세트 사용)nftables inet filter forwardINPUT체인이며 / 를 사용하지 않습니다 input.

게다가올바른 연결을 방해하는 규칙 누락주인.

inet filter input

입력 경로는 다음을 제외하고 Docker 컨테이너에 전혀 사용되지 않습니다.도커 에이전트이 사례는 일반적으로 localhost 액세스에 사용되지만 OP는 이미 승인했으므로 iif lo accept이 답변에서는 더 이상 처리할 필요가 없습니다. Docker에 대한 내용은 여기에 없어야 합니다. 컨테이너 포트 80 및 6200에 대한 참조는 쓸모가 없으므로 제거해야 합니다.

그러면 Docker와 상관없이입력하다체인이 상태 규칙을 놓쳤습니다. 이것이 없으면 호스트의 출력(DNS 쿼리)에서 트래픽이 반환됩니다.회신하다, 평평한회신하다, 업그레이드 다운로드 중...)이 실패합니다. 이것을 사용하십시오 :

    chain input {
            type filter hook input priority 0; policy drop;
            ct state related,established accept
            iif lo accept
            iif eno2 icmp type echo-request accept
            iif eno2 ip 192.168.0.0/16 tcp dport 22 accept
            iif eno2 ip 192.168.0.0/16 tcp dport 443 accept
    }

입력 경로에는 여전히 추가 규칙이 필요합니다.도커 자체(대신에그 컨테이너): Docker API(보안 고려 사항이 허용하는 경우) 또는 사용되는 VxLAN과 같은 다양한 기능에 대한 원격 액세스를 허용하려면 규칙이 필요할 수 있습니다.부두 노동자들의 군중.

inet filter output

마찬가지로 OP inet filter output체인의 삭제 정책은 호스트 연결(DNS)을 종료합니다.문의, 평평한필요하다또는 다운로드를 시작할 수 없습니다. 등). policy accept호스트 자체에서 나가는 필수 트래픽에 대한 예외가 있거나 추가 되어야 합니다 . 체인에는 다음이 포함되어야 합니다.적어도이 같은:

  chain output {
          type filter hook output priority 0; policy drop;
          ct state related,established accept
          oif lo accept
          udp dport { 53, 123 } accept
          tcp dport { 53, 80, 443 } accept
          icmp type echo-request accept
  }

컨테이너의 패킷은 이러한 체인에 의해 평가되지 않지만 forward체인에 의해 평가되며 제한되지 않습니다.

IPv6

사용인트라넷ICMPv6이 제대로 활성화되지 않은 경우 IPv6 제품군은 IPv6이 ARP에 의존하지 않고(방화벽을 거의 사용하지 않음) 대신 링크 로컬 연결을 위해 ICMPv6에 의존하기 때문에 모든 IPv6 연결을 차단합니다. 집을 사용하거나 ip(그리고 다음을 제외하고 사용)필터테이블과의 충돌을 피하기 위해iptables-nft) 또는 ICMPv6을 올바르게 처리하십시오. 모두 수락하거나 올바른 방향 input에 필요한 것이 무엇인지 확인하십시오.outputSLAAC(새로운 민주당:RS, RA, NS, NA, ...), 핑 ... 처리 중입니다.

관련 정보