socat で tap インターフェースを作成して認証も暗号化もしないVPN
概要
socat で TUN/TAP インターフェースを扱えるらしく、 UDP で転送すれば簡単な VPN が構成できそうだったので、やってみた。 認証も暗号化も行わない。 想定する環境は↓。
サーバ | クライアント | |
---|---|---|
OS | Linux | Linux |
UDPで接続するIP | 192.168.1.1 | 192.168.1.2 |
tap1のIP | 10.0.0.1/24 | 10.0.0.2/24 |
サーバ側
サーバ側で↓を行うと UDP の1194番ポートで Listen される。
一応、↑では range
オプションでクライアントのIPからのみ許可するように設定しているが、 セキュリティ的にはよくはない。
そして、この段階ではまだサーバ側には tap1 インターフェースはできていないはず。
クライアント側
サーバ 192.168.1.1:1194
につなぎに行くように↓を行う。
するとクライアント側に tap1
インターフェースが作成された。
$ ip link show tap1
56: tap1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000
link/ether ce:2d:c2:a5:12:f0 brd ff:ff:ff:ff:ff:ff promiscuity 1
IPアドレス 10.0.0.2/24
も付加されている。
$ ip addr show tap1
56: tap1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
link/ether ce:2d:c2:a5:12:f0 brd ff:ff:ff:ff:ff:ff promiscuity 1
tun
inet 10.0.0.2/24 brd 10.0.0.255 scope global tap1
valid_lft forever preferred_lft forever
ping をクライアントからサーバへ打つ
この状態で ping をクライアント側からサーバ側 10.0.0.1
へ打ってみると ping が返ってくる。
$ ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=2.20 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.750 ms
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.748 ms
そして、サーバ側に tap1
インターフェースが作成されていることがわかる↓。
$ ip addr show tap1
39: tap1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
link/ether ee:fe:01:71:e7:87 brd ff:ff:ff:ff:ff:ff promiscuity 1
tun
inet 10.0.0.1/24 brd 10.0.0.255 scope global tap1
valid_lft forever preferred_lft forever
MTUの調整
上記で作成された tap1
インターフェースの MTU をサーバ側とクライアント側の両方で設定しておく。
Layer | byte |
---|---|
IP | 20 |
UDP | 8 |
Ethernet | 18 |
tap デバイスはイーサネットのフレームも含むため、 L3 までに含まれるの各種ヘッダの量は↑である。 したがって、VPN を張りたい経路の MTU が 1500 の場合、 tap1 に設定されるべき MTU は (1500 - 20 - 8 - 18)
=> 1454
と計算できる。
備考
TUN/TAP のうち TAP にしたかったのは仮想ブリッジに接続したかったからだが、 仮想ブリッジの作成まで記事に含めるのは冗長な気がしたので、 tap1
インターフェースに直接 IP を振った。
ちなみに、socat は openssl も使えるため暗号化できそうだが、 残念ながら TCP をバインドしてしまって、UDP では不可能だった。 一方で、openssl s_server
で DTLS を指定すると UDP をバインドすることは確認できたので、 そのうち socat も対応してくれそうな気がする。