UDP にコネクションはあるのか
UDPはステートレスと、教科書では習うが。実際にはUDPはステートがある。
conntack で見てもわかるのですが。ss でパケットがESTABLISHEDになってたりする。
実験環境
最初に実験環境を整理しておく
ネットワーク構成を作る。
実際の構成は次の通り。
準備
lxc と netns で実験環境を作る。
## コンテナ作成 lxc launch ubuntu:22.04 t01 lxc config set t01 security.nesting true lxc restart t01 lxc shell t01 ## ncat インストール echo 'Acquire::HTTP::Proxy "http://apt-cacher.lan";' | tee /etc/apt/apt.conf.d/01proxy apt update && apt upgrade -y apt install ncat ## デバイス追加 ip link add name veth0 type veth peer name veth0-c01 ip netns add c01 ip link set veth0-c01 netns c01 ip netns exec c01 ip link set veth0-c01 name eth0 ip link set veth0 name eth1 ## アドレス追加 ip netns exec c01 ip addr add 10.2.0.2/24 dev eth0 ip addr add 10.2.0.1/24 dev eth1 ## リンクアップ ip netns exec c01 ip link set eth0 up ip link set eth1 up ## ルーティング ip netns exec c01 ip route add default via 10.2.0.1 dev eth0
疎通確認する。
lxc shell t01 ncat -ul 10.2.0.1 80
もう一つ別の端末で、ncatへ接続する
lxc shell t01 ip netns exec c01 ncat -u 10.2.0.1 80
双方で文字列を送信できて通信できたらOK
REJECT する。
通信拒否を入れてあげて、パケットが拒否されることを確認
iptables -A OUTPUT -p udp --sport 80 -d 10.2.0.2 -j REJECT
ESTABLISHED(通信確立)は許可する。
iptables -A OUTPUT -p udp --sport 80 -d 10.2.0.2 -j REJECT iptables -I OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
ESTABLISHEDを許可すると、応答できることがわかる。
ここから「コネクション確立」という<状態>がUDPにあるとわかる。
UDPにESTABLISHEDはある。
この実験で分かる通り、ESTABLISHEDでチェックしている。
UDPは 宛先IP/ポートで区別していて、送信先を記憶している。なので接続の確立はわかる。
具体的な話を考えるときりがないけど、UDPはSRC/DSTをチェックして接続を見ていると思っておくといい。IPレベルでコネクションがあり、完全なステートレスというわけでもない。UDPはステートレスでいくらでも送れるが、応答パケットはIP/ポートで識別している。
その他の確認方法
ncat -lu 0.0.0.0
で接続待ちを作って、他のIPから接続すると接続できない。なので動きがよく分かる。
まとめ
UDPは規格はステートレスではあるが、実際のLinux実装では、ある程度ステートがある。
送信元で識別して接続状態を作ってる。(パケットに応答するため、どこから繋がったかを管理している、つまり状態がある)ということになるのかな。
参考資料
https://serverfault.com/questions/123208/iptables-p-udp-state-established