tc
DHCPリレーネットフィルタ(どちらか一方)を使用せずにnftables
ブリッジに接続されているDockerコンテナにDHCPブロードキャストパケットをルーティングすることができるかどうか疑問に思います。
これは、macvlan
DHCPコンテナを使用したくないため、1つのIP(つまりルータIP)がすべてのネットワークタスクを処理しているように見えるためです。 DHCPは通常コンテナに必要であり(DHCPは無差別モードを要求するため)、これがなければホストのネットワークスタックを制御できることをCAP_NET_ADMIN
知っています(コンテナでもこれを行います)。macvlan
userns-remap
DHCPパケットを修正して転送できるといいですね。リレーは、macvlan
DHCPコンテナがすでに持っているのと同じ方法がまだ必要なため、ここでは機能しません。
これは可能ですか?ありがとう
答え1
そういうことですが、私には不完全な解決策があります。このソリューションの効率は、ネットワーク構成によって異なります。
DHCPサーバーはDockerブリッジネットワーク内にあり、および経由で実行されるため、実行されるネットワーク名前空間を制御できますCAP_NET_BIND
。CAP_NET_RAW
CAP_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を偽装できない場合は、パケットを変更してSIADDR
DHCPを変更する必要があります。オプション54(サーバー識別子)。
この構成により、Docker ブリッジの背後で DHCP サーバーを使用できるため、元の質問で提起された要件を満たすことができます。
答え2
はい、可能です。 DHCPは完全なUDP / IPプロトコルであり、nftables
IPソースアドレスが0.0.0.0、ブロードキャストターゲットが255.255.255.255 FF:… :FFのすべてのイーサネットフレームをネットワークインターフェイスとIPアドレスに転送できる必要があります。あなたのコンテナ。
ただし、DHCPサーバーソフトウェアはそれを望まないかもしれません。レイヤ2(AF_PACKET
通常はソケットタイプSOCK_RAW
、プロトコルを使用)ソケットETHER_TYPE
(インタフェースを参照)にバインドする必要があるかもしれません。状況によって異なりますが、ほとんどのDHCPサーバーを構成できます。man 7 packet
AF_INET
SOCK_DGRAM