iptablesでルータを作る
Ubuntu Linuxでiptablesを使って、ネットワークの練習をする。WEBサイトに潤沢な検索結果があってとくにメモを残してない。
いつもiptablesを検索し直してて非効率なので、ここらで一旦まとめ直しておく。
今回は、lxc ホストと ip netns を使って作ることにする。
ネットワーク構成を考える。
実際の構成
ネットワーク構成をLXCと ip netns を駆使して次のように構成する。
準備 (構成を作る)
lxc でコンテナを作成し、デバイスを追加し、ip nets でネットワークを名前空間で作る。
## コンテナ作成 lxc launch ubuntu:22.04 t01 lxc config set t01 security.nesting true lxc restart t01 lxc shell t01 ## デバイス追加 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
マスカレードを作る
準備した構成を使ってMASQURADEを作る
## マスカレード iptables -t nat -A POSTROUTING -o eth0 -s 10.2.0.0/24 -j MASQUERADE
## パケット送信して確認 ip netns exec c01 ping 1.1.1.1
後片付け
## 後片付け iptables -t nat -D POSTROUTING -o eth0 -s 10.2.0.0/24 -j MASQUERADE
SNAT / source NAT を作る
## SNAT iptables -t nat -A POSTROUTING -o eth0 -s 10.2.0.0/24 -j SNAT --to-source 10.78.33.235 ## 後片付け iptables -t nat -D POSTROUTING -o eth0 -s 10.2.0.0/24 -j SNAT --to-source 10.78.33.235
## パケット送信して確認 ip netns exec c01 ping 1.1.1.1
DNAT / destination NATを作る
DNATの例 1
# eth0 に入った tcp ポート 334宛 のパケットは10.2.0.2に転送する iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 334 -j DNAT --to-destination 10.2.0.2
接続の確認
## リッスン(サーバ) takuya@t01:~$ ip netns exec c01 nc -l 10.2.0.2 334 ## 接続(クライアント) takuya@raspi-ubuntu:~$ nc 10.78.33.235 334
DNATの例2.1
# eth0 に入った tcp://10.78.33.235:334 宛 のパケットはtcp://10.2.0.2:334に転送する iptables -t nat -A PREROUTING -i eth0 -p tcp -d 10.78.33.235 --dport 334 -j DNAT --to-destination 10.2.0.2
DNATの例2.2
# eth0 に入った tcp://10.78.33.235:334 宛 のパケットはtcp://10.2.0.2:3304に転送する iptables -t nat -A PREROUTING -i eth0 -p tcp -d 10.78.33.235 --dport 334 -j DNAT --to-destination 10.2.0.2:3304
DNATの例3 icmp
# eth0 に入った icmpパケットはすべて10.2.0.2に転送する iptables -t nat -A PREROUTING -i eth0 -p icmp -j DNAT --to-destination 10.2.0.2
接続の確認
## パケット確認 takuya@t01:~$ tcpdump -n -i eth1 icmp # パケットがでていくことを確認 ## パケット送信 takuya@raspi-ubuntu:~$ watch -dc -n 1 ping -c 1 10.17.238.144
DNATの例4 UDP
# eth0 に入った icmpパケットはすべて10.2.0.2に転送する iptables -t nat -A PREROUTING -i eth0 -p udp --port 443 -j DNAT --to-destination 10.2.0.2
接続の確認
## リッスン(サーバ) takuya@t01:~$ ip netns exec c01 nc -l -u 10.2.0.2 334 ## 接続(クライアント) takuya@raspi-ubuntu:~$ nc -u 10.78.33.235 334
DNATを試すときの注意。
- pingで送信しっぱなししてても、icmp_seq で継続パケットになり、送信先の切替が起きないため、watchで1回きりの送信を継続する。
- t01 からパケット送出すると自分自身からなので、OUTPUTをとおり、PREROUTINGを取らないのでDNATにならない
- DNATでは、-d IP を省略して -d 0.0.0.0/0すれば、eth0 を通るすべてのパケットが対象になる。
- ncコマンドは
nc -l ip port
でtcpサーバーnc ip port
でクライアントになる。適当にキーボードを叩いてEnterする。 - nc コマンドは
nc -u
でUDPになる。
パケットのフォワードとルーティング・テーブルの関係
次のように、ルーティングテーブルを参照して転送される。
iptablesはこのルーティング・テーブルの前後に挟み込まれる。
制限をかける。
まとめ
ipablesのフックポイントの全体像
おまけ
ルーティング・テーブルを切り替えてみる。
iptablesはルーティング・テーブルを切り替えると、インタフェースが変わるのを体験する。
ネットワーク構成(コンテナ+bridge+netns)を作る
veth2/ br1 の2つのNICのどちらを使うかを選ぶようにする。
構成を作る
## コンテナ準備 lxc restart t01 lxc shell t01 ## デバイス追加 ip link add br1 type bridge ip link add name veth1 type veth peer name veth1-br1 ip link add name veth2 type veth peer name veth2-br1 ip link set veth1-br1 master br1 ip link set veth2-br1 master br1 ## netns 作成 ip netns add c01 ip link set veth1 netns c01 ip netns exec c01 ip link set veth1 name eth0 ## IP割当 ip addr add 10.2.0.1/24 dev br1 ip addr add 10.2.0.3/24 dev veth2 ip netns exec c01 ip addr add 10.2.0.2/24 dev eth0 ## リンクアップ ip link set br1 up ip link set veth2 up ip link set veth1-br1 up ip link set veth2-br1 up ip netns exec c01 ip link set eth0 up ip netns exec c01 ip link set lo up ## ルーティング ip netns exec c01 ip route add default via 10.2.0.1
netns c01 のデフォルトGWを切り替えて試す。
## パケットのフィルタリング ip netns exec c01 iptables -t mangle -I POSTROUTING -o eth0 -j DROP ## デフォルト・ゲートウェイの指定 ip netns exec c01 ip route add default via 10.2.0.1 ## 後片付け ip netns exec c01 ip route del default via 10.2.0.1 ## デフォルト・ゲートウェイを切り替える。 ip netns exec c01 ip route add default via 10.2.0.3 ## 後片付け ip netns exec c01 ip route del default via 10.2.0.3
## veth2 経由はbr-veth間を通信として処理する。 sudo sysctl net.bridge.bridge-nf-call-iptables=0 ## ipの切替時にarp/neighリフレッシュが必要かもしれない、 ip netns exec c01 ip neigh flush dev eth0
2023-10-18
DNAT書いてなかったので、書いた。