VPNからsshuttleに切り替えてから、不便だなぁと思っていたのはDNSリクエストを転送できないことだった。 VPNの接続先のDNSサーバに接続して、リモート先の内部で利用しているドメインを正引きするのに使っていた。 sshuttleはSSHのポートフォワードを元にしたツールなので、UDPなDNSリクエストを転送できないと思いこんでいた。 が、なんとDNSリクエストを転送できることに気がついた!
--dns capture local DNS requests and forward to the remote DNS server --ns-hosts IP[,IP] capture and forward DNS requests made to the following servers --to-ns IP[:PORT] the DNS server to forward requests to; defaults to servers in /etc/resolv.conf on remote side if not given.
--dnsオプション
--dns
を指定していると、ローカル環境のDNSリクエストをリモートのDNSサーバに転送するようになる。
具体的な動作としてはresolv.confやresolvctl statusなどを見て、それらに設定されているDNSサーバへのリクエストをiptablesを使ってshuttleのトンネルにリダイレクトしているようだ。
❯ sudo iptables -nvL -t nat -- snip -- Chain sshuttle-12300 (2 references) pkts bytes target prot opt in out source destination 0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0 TTL match TTL == 63 0 0 REDIRECT udp -- * * 0.0.0.0/0 127.0.0.53 udp dpt:53 redir ports 12299 👈 私の環境に設定されているDNSサーバの設定がリダイレクトされている 0 0 REDIRECT udp -- * * 0.0.0.0/0 127.0.0.54 udp dpt:53 redir ports 12299 👈 0 0 REDIRECT udp -- * * 0.0.0.0/0 192.168.0.1 udp dpt:53 redir ports 12299 👈 -- snip -- ❯ sudo ss -unlp State Recv-Q Send-Q Local Address:Port Peer Address:Port Process UNCONN 0 0 127.0.0.1:12299 0.0.0.0:* users:(("sshuttle",pid=938219,fd=8)) 👈 udp:12299はshuttleが使っている -- snip -- ☆リモートサーバを見る $ ss -unp Recv-Q Send-Q Local Address:Port Peer Address:Port Process 0 0 127.0.0.1:41739 127.0.0.53:53 users:(("python3",pid=32560,fd=11)) 👈 sshuttleがリモートのpython3を起動してポートフォワードしている -- snip -- $ ps auxwwff | grep 32560 user 32560 0.1 0.1 18920 12252 ? Ss 23:53 0:00 \_ python3 -c import sys, os; verbosity=0; sys.stdin = os.fdopen(0, "rb"); exec(compile(sys.stdin.read(1486), "assembler.py", "exec"))
すべてのDNSリクエストを転送してしまうので、特定ドメインのリクエストのみ転送したいという時はこちらは使えない。
--ns-hosts オプション
--ns-hosts
オプションを使うとこのオプションで指定したIPへのDNSリクエストのみ転送することができる。
例えば 192.0.2.1
と 192.0.2.2
へのリクエストを転送したい場合は --ns-hosts 192.0.2.1,192.0.2.2
みたいなオプションになる。
このオプションをつけてsshuttleを起動すると以下のようなiptablesルールが追加される。
Chain sshuttle-12299 (2 references) pkts bytes target prot opt in out source destination 0 0 RETURN all -- * * 0.0.0.0/0 0.0.0.0/0 TTL match TTL == 63 0 0 REDIRECT udp -- * * 0.0.0.0/0 192.0.2.1 udp dpt:53 redir ports 12298 👈 追加されたルール 0 0 REDIRECT udp -- * * 0.0.0.0/0 192.0.2.2 udp dpt:53 redir ports 12298 👈 -- snip --
リモートの状態等々は --dns
オプションのときと同じ。
dnsmasqなどと組み合わせて特定のドメインのみ、転送先のDNSサーバのIPにする。
例えば、dnsmasqでexample.comのリクエストのみ192.0.2.1 / 192.0.2.2 にするには以下のような設定になる。
$ cat /etc/dnsmasq.conf server=/example.com/192.0.2.1 server=/example.com/192.0.2.2
--to-ns オプション
デフォルトでは転送先のDNSサーバは、リモートサーバの/etc/resolv.confに従うのだが、--to-ns
オプションを使うと変更できる。
っとヘルプに書いてあるのだが未検証。
おわりに
sshuttleに --dns / --ns-hostsを指定することでDNSリクエストを転送することができる。 転送先のDNSサーバはIPだけではなくPORTも指定できるようなので、リモート先のConsul DNSを参照するということができると思う。 sshuttleを使えばDNSリクエストの転送もできるので、L2で通信する必要がないのであればVPNよりお手軽なSSHトンネルでいいのではと言う気がしている。便利だ。