netfilter가 DHCP 릴레이 역할을 할 수 있나요?

netfilter가 DHCP 릴레이 역할을 할 수 있나요?

tcDHCP 릴레이 넷필터(둘 중 하나)를 사용하지 않고 nftables브리지에 연결된 Docker 컨테이너로 DHCP 브로드캐스트 패킷을 라우팅하는 것이 가능한지 궁금합니다 .

그 이유는 macvlanDHCP 컨테이너를 사용하고 싶지 않아서 하나의 IP(즉, 라우터 IP)가 모든 네트워크 작업을 처리하는 것처럼 보이기 때문입니다. DHCP는 일반적으로 컨테이너에 필요하며 (DHCP는 무차별 모드를 요구하기 때문에) 이것이 없으면 호스트의 네트워크 스택을 제어할 수 있다는 CAP_NET_ADMIN것을 알고 있습니다 ( 컨테이너에서도 이 작업을 수행합니다).macvlanuserns-remap

DHCP 패킷을 수정하여 전달할 수 있으면 좋을 것 같습니다. 릴레이는 macvlanDHCP 컨테이너가 이미 가지고 있는 것과 동일한 방법이 여전히 필요하기 때문에 여기에서는 작동하지 않습니다 .

이것이 가능한가? 감사해요

답변1

그런 것 같은데, 제게는 불완전한 해결책이 있습니다. 이 솔루션의 효율성은 네트워크 구성에 따라 달라질 수 있습니다.

DHCP 서버는 Docker 브리지 네트워크 내에 위치하며 , 및 을 통해 실행되므로 실행되는 네트워크 네임스페이스를 제어할 수 있습니다 CAP_NET_BIND.CAP_NET_RAWCAP_NET_ADMIN

~을 위한DHCPDISCOVER패킷이 DHCP 서버에 도착하면 다음 규칙이 사용됩니다.

table netdev filterearly_lan {
    chain ingress {
        type filter hook ingress device eth0 priority -500; policy drop;
        
        ip saddr 0.0.0.0 ether daddr ff:ff:ff:ff:ff:ff ip daddr 255.255.255.255 udp sport 68 udp dport 67 ip saddr set $LOCAL_NETWORK ip daddr set $DHCP meta pkttype set host accept;
    }
}

이렇게 하면 다음에 나열된 문제를 피할 수 있습니다.이것문제는 패킷이 정상적으로 넷필터를 통과하여 다음 주소로 전송될 수 있다는 의미는 아닙니다 NFQUEUE.

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

        udp sport 68 udp dport 67 queue num 0;
        udp sport 67 udp dport 68 queue num 0;
    }
}

$LOCAL_NETWORK서브넷 내의 모든 IP가 될 수 있지만 어떤 이유로 로컬 장치의 IP가 될 수는 없습니다. 네트워크 주소(예: 192.168.1.0)로 설정할 수 있는 것 같습니다. 대상 MAC 주소를 변경할 필요는 없는 것 같습니다.

브로드캐스트 요청으로 응답하는 클라이언트를 처리하려면 라우팅을 위해 패킷 유형을 호스트로 변경해야 하며 다음에서 얻을 수 있습니다.DHCPOFFER패킷( ingress인터페이스에 구애받지 않도록 여기에서는 사용되지 않음):

table inet filter {
    chain raw {
        type filter hook prerouting priority -400; policy accept;

        ip daddr 255.255.255.255 udp sport 67 udp dport 68 @nh,128,32 set @th,192,32 meta pkttype set host;
    }
}

DHCPOFFER패킷이 유니캐스트로 전송 되면질문postrouting클라이언트가 IP를 얻기 전에 클라이언트에게 ARP 요청이 이루어집니다(이 단계에서). 이 문제를 우회하려면:

table inet mangle {
    chain postrouting {
        type filter hook postrouting priority 50;

        udp sport 67 ether daddr set ff:ff:ff:ff:ff:ff ip daddr set 255.255.255.255;
    }       
}

ARP 요청이 발행되면 ARP 요청 내용에서 대상 MAC 및 IP를 복구할 수 있습니다.DHCPOFFER올바른 목적지로 보내세요. 패킷 분석 중에 의심이 발생하지 않도록 TTL도 복원해야 합니다.

table netdev filterearly_lan {
    chain egress {
        type filter hook egress device eth0 priority 500; policy accept;

            #Restore the TTL that is changed during the routing process
            udp sport 67 ip ttl set 64 continue;                        
            #Client asked for broadcast
            udp sport 67 @th,256,48 0x800000000000 ip daddr set 255.255.255.255 ether daddr set ff:ff:ff:ff:ff:ff;
            #Set the ether addr to the CHADDR. Only if unicast flag
            udp sport 67 @th,256,48 0x000000000000 @ll,0,48 set @th,400,48;
            #Set the ip daddr from the YIADDR. Only if unicast flag
            udp sport 67 @th,256,48 0x000000000000 @nh,128,32 set @th,304,32;
    }
}

대답은 다음과 같아야합니다.SNAT다른 네트워크에서 왔으므로 올바르게 편집되었습니다.

table inet nat {
    chain postrouting {
        type nat hook postrouting priority 100; policy accept;

        oifname "eth0" masquerade;
    }
}

DHCP 서버 구성과 패킷에 필요한 수정 사항은 이 질문과 대답의 범위를 벗어납니다. 이상적으로는 DHCP 서버가 다양한 네트워크에 IP 주소 제공을 지원합니다. 서버가 IP를 스푸핑할 수 없으면 패킷을 수정하여 SIADDRDHCP를 변경해야 합니다.옵션54(서버 식별자).

이 구성을 사용하면 Docker 브리지 뒤에서 DHCP 서버를 사용할 수 있으므로 원래 질문에서 제기된 요구 사항을 충족할 수 있습니다.

답변2

예, 가능해 보입니다. DHCP는 완벽한 UDP/IP 프로토콜이며 nftablesIP 소스 주소가 0.0.0.0이고 브로드캐스트 대상이 255.255.255.255 FF:…:FF인 모든 이더넷 프레임을 네트워크 인터페이스 및 IP 주소로 전달할 수 있어야 합니다. 귀하의 컨테이너.

그러나 DHCP 서버 소프트웨어는 이를 원하지 않을 수 있습니다. 계층 2( AF_PACKET일반적으로 소켓 유형 SOCK_RAW, 프로토콜 사용 ) 소켓 ETHER_TYPE(인터페이스 참조 ) 에 바인딩해야 할 수도 있습니다 . 상황에 따라 다르지만 대부분의 DHCP 서버를 구성할 수 있을 것입니다.man 7 packetAF_INETSOCK_DGRAM

관련 정보