OpenSSHでVPNを構築する(tap編)
sshさえ通ればなんでもできる、とはよく言われることです。勤務先などで、ネットワークの制限が厳しくて、困っている方もいるのではないでしょうか。
最近のOpenSSHは、OSのtun/tapデバイスを利用して、VPNを構築することができます。tunを利用したVPNは解説がいくつかあったのですが、tapを利用してVPNを構築する方法(特に日本語)の解説がみつからなかったので、自分で行った設定をまとめてみます。前提条件は、以下の通りです。
- クライアント/サーバの双方がUNIX系である
- クライアント/サーバの双方にrootでアクセスできる
- サーバ側でiptablesの設定が可能
- サーバ側のネットワークへのアクセスが必要でないなら不要
- ブリッジネットワークの設定が可能な人なら不要
さて、tapでは仮想ネットワークが構成されます。ここでは、次のようなネットワーク設定を用いることにします。また、クライアントからサーバを経由してのネットワーク接続ができるような設定にもします。
マシン | インターフェース名 | IPアドレス | ネットマスク |
---|---|---|---|
server | tap0 | 192.168.100.1 | 255.255.255.0 |
client | tap0 | 192.168.100.2 | 255.255.255.0 |
さて、実際にVPN接続の設定に移ります。特権アカウントでの手動ネットワーク設定がかかわるところなので、Debian系列とRedHat系列で設定ファイルが異なります。以下はすべてDebian GNU/Linux (squeeze以降)を仮定します。
rootでのssh接続を可能にする
サーバ側の/etc/ssh/sshd_configの設定変更
最低セキュリティを次の設定まで緩めないといけません。tapだけでなく、tunなVPNも利用する予定があるならPermitTunnelをyesにしましょう。
PermitRootLogin forced-commands-only PermitTunnel ethernet
サーバ側の/root/.ssh/authorized_keysへ公開鍵の登録
さすがにrootでのパスワード認証を常にOKするのはまずいので、クライアント側でVPN用の鍵を作ります。この鍵は、VPN構築専用で、自動化するためにパスフレーズを空にします。なお、パスフレーズが空でも、秘密鍵さえちゃんと安全に管理しておけば、パスワード認証よりも安全です。今回の事例では、tapvpnという名前にします。
client$ sudo -H ssh-keygen -t rsa -f tapvpn Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/tapvpn): Enter file in which to save the key (/root/.ssh/tapvpn): Created directory '/root/.ssh'. Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/tapvpn. Your public key has been saved in /root/.ssh/tapvpn.pub. The key fingerprint is: dc:f1:54:b9:1c:21:9d:3a:70:59:b2:50:55:ad:3f:ec root@client The key's randomart image is: +--[ RSA 2048]----+ | ..+===o| | ..o== .| | .ooo + | | . . +o + | | S . .... | | o.| | . .| | E | | | +-----------------+
公開鍵の内容を一般ユーザ環境にコピーして、tapデバイスの設定と制限を行います。
client$ sudo cp /root/.ssh/tapvpn.pub . ... client$ cat tapvpn.pub no-X11-forwarding,no-agent-forwarding,no-pty,tunnel="0",command="/sbin/ifdown tap0; /sbin/ifup tap0" ssh-rsa AAAA....== root@client
次に、上記のように作ったVPN用の公開鍵(/root/.ssh/tapvpn.pub)をサーバにコピーします。一般ユーザならssh-copy-idコマンドで一発なのですが、サーバにrootで直にログインすることはできないですし、一般ユーザでserverにログインします。なお、server上のアカウントではsudoでなんでもできることを仮定します。
client$ scp tapvpn.pub server: client$ ssh server server$ echo tapvpn.pub | sudo tee -a /root/.ssh/authorized_keys
なお、authorized_keysにオプションを指定するのもよいでしょう。この段階で、クライアントからrootで認証が成功するかどうかを試しておきましょう。シェルのコンソールはでなくとも、認証が通っていれば成功です。Ctrl-Cで終了してください。
client$ sudo -H ssh -v -i /root/.ssh/tapvpn server
クライアント側での/root/.ssh/configの編集
tapの設定をコマンドラインで行うのは面倒なので、一発接続ができるように設定を行います。/root/.ssh/configを編集します。
client$ sudo cat /root/.ssh/config ... Host server-vpn HostName server IdentityFile %d/.ssh/tapvpn Tunnel ethernet TunnelDevice 0
サーバ側でのネットワーク設定の編集
ここまでで、仮想ネットワークデバイスの準備はできているのですが、IPなどの設定が一切していません。今回は、クライアントからはサーバ側のネットワークにサーバマシンによるiptablesによるNATを使って接続する設定にします。変更するのは/etc/network/interfacesです。
server$ cat /etc/network/interfaces ... auto eth0 iface eth0 inet static address XXX.XXX.XXX.XXX netmask YYY.YYY.YYY.YYY pre-up echo 1 > /proc/sys/net/ipv4/ip_forward pre-up iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -j MASQUERADE ... iface tap0 inet static address 192.168.100.1 netmask 255.255.255.0
クライアント側のネットワーク設定
今回は、ドラスティックに、クライアントマシンからの通信は、すべてサーバ側を経由するようにします。なお、autosshパッケージを利用します。また、やはり/etc/network/interfacesを編集します。サーバの実IPアドレスがXXX.XXX.XXX.XXX、クライアントの(VPN接続前の)ゲートウェイのアドレスをZZZ.ZZZ.ZZZ.ZZZとします。
client$ cat /etc/network/interfaces ... iface tap0 inet static pre-up autossh -f server-vpn pre-up sleep 5 address 192.168.100.2 netmask 255.255.255.0 up route add XXX.XXX.XXX.XXX gw ZZZ.ZZZ.ZZZ.ZZZ eth0 up route add default gw 192.168.100.1 tap0 up route del default gw ZZZ.ZZZ.ZZZ.ZZZ eth0 down route add default gw ZZZ.ZZZ.ZZZ.ZZZ eth0 down route del default gw 192.168.100.1 tap0 down route del XXX.XXX.XXX.XXX gw ZZZ.ZZZ.ZZZ.ZZZ eth0 post-down killall autossh