はじめに
TP-LINK TL-WR902ACというトラベルルーターにOpenWrtとOpenVPNをいれて旅先VPNサーバをつくってみました。大学時代に流行った某RTSゲームを温泉旅館で合宿という名目で年一ぐらいで開催してたんですが、さすがにこのご時世、何人か参加できないとのことで、リモートから乗り込める環境を構築してみました。(ちなみに今年は、富山の宇奈月温泉で開催しました。)
お断り
OpenWrt化は自己責任でお願いします。
準備したもの
- TP-LINK TL-WR902AC(3000円ぐらい)
- Google Pixel 3a(買ったけど使ってなかったスマホ)
- NifMoのSIM (3GBで900円。グローバルIPもらえる!)
構成
※Pixel 3aとTL-WR902AC間はUSB接続でテザリングします。
準備
公式サイトの手順通りに進めますが、まずTFTPサーバが必要だったので、Windows10上のWSL上にUbuntu20.04をインストールして、そこにtftpd-hpaをいれて作業します。
WSL(Ubuntu)上で準備
- tftpサーバをいれる。(WSL上での操作)
sudo apt install tftpd-hpa
- ファームを/srv/tftp/にダウンロードし、tp_recovery.binにリネーム(WSL上での操作)
cd /srv/tftp
sudo wget http://downloads.openwrt.org/releases/19.07.5/targets/ramips/mt76x8/openwrt-19.07.5-ramips-mt76x8-tplink_tl-wr902ac-v3-squashfs-tftp-recovery.bin
sudo mv openwrt-19.07.5-ramips-mt76x8-tplink_tl-wr902ac-v3-squashfs-tftp-recovery.bin tp_recovery.bin
- TFTPサーバのIPは、「192.168.0.66」にする必要があるのでWindows上でTL-WR902ACと接続するネットワークアダプタのIPアドレスを変更。(Windows上での操作)
- WSL2でtftpdを起動する。WSLの場合、systemctlから起動できないので、コマンドラインで直起動。(WSL上での操作)
sudo /usr/sbin/in.tftpd --listen --user tftp --address :69 --secure /srv/tftp
- tftpのポートを開くとファイアウォール設定の画面が表示されるので許可する。(Windows上での操作)
- PCとTL-WR902ACを直結
OpenWrt化
- TL-WR902ACのリセットボタンをSIMピンとか爪楊枝とかの細い棒で押しっぱなしにした状態で電源ON(USBケーブルを刺す)
- 20秒ほど押しっぱなしにすると電源LED下のLEDがチカチカしだすのでリセットボタンから離す。OpenWrtファームに書き換わる。
- しばらくすると自動で再起動
- ブラウザでhttp://192.168.1.1/ にアクセス。OpenWrtのログイン画面が出れば成功。
OpenWrtの設定
IPアドレスの変更とDHCPサーバの無効化
初期設定でDHCPサーバが有効なので無効化とIPアドレスを変更します。WebUIから変更するとうまく変更出来なかったのでsshログインして、uciコマンドで以下を打つ。
(ここではまた有線側からインターネットへ接続できるIPアドレス(192.168.249.220)を設定しています。)
uci del dhcp.lan.start
uci del dhcp.lan.limit
uci del dhcp.lan.leasetime
uci set dhcp.lan.ra_management='1'
uci set dhcp.lan.ignore='1'
uci set network.lan.ipaddr='192.168.249.220'
uci set network.lan.gateway='192.168.249.1'
uci add_list network.lan.dns='192.168.249.1'
uci commit
/etc/init.d/network restart
OpenVPNのインストール
ここも基本は、公式サイトの手順を元に進めます。
sshログインして以下を実行
opkg update
opkg install openvpn-openssl openvpn-easy-rsa
OpenVPNの設定
証明書の作成
秘密鍵のパスワードはなしです。sshログインして以下を実行
cd /etc/openpvn/
easyrsa init-pki
easyrsa gen-dh #結構時間かかる。。
easyrsa build-ca nopass #「Common Name」聞かれたら適当に入力
easyrsa build-server-full server nopass
easyrsa build-client-full client nopass
openvpn --genkey --secret ta.key
「easyrsa gen-dh」は、1時間13分ぐらいかかったので、気長に待ちましょう。。
root@OpenWrt:/etc/openvpn# time easyrsa gen-dh
Note: using Easy-RSA configuration from: /etc/easy-rsa/vars
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
....................................................+...........................
(略)
..................................................................++++++++DH parameters of size 2048 created at /etc/openvpn/pki/dh.pem
real 1h 13m 42s
user 1h 13m 28s
sys 0m 2.86s
サーバ設定ファイル作成
内容は以下で、/etc/openvpn/server.confとして保存。tcpの1194ポート、tunデバイスで起動。クライアントには、「10.8.0.0/24」を割り当てます。今回は、クライアント証明書の重複を許す設定をしているのでクライアントに配布する証明書は一つだけです。セキュリティ気にするなら、個々にクライアント証明書を作りましょう。
cat << EOF > /etc/openvpn/server.conf
port 1194
proto tcp
dev tun
ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/issued/server.crt
key /etc/openvpn/pki/private/server.key
dh /etc/openvpn/pki/dh.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist /var/log/openvpn-ipp.txt
push "route 192.168.249.0 255.255.255.0"
client-to-client
duplicate-cn #クライアント証明書の重複を許す設定
keepalive 10 120
tls-auth ta.key 0
cipher AES-256-CBC
persist-key
persist-tun
status /var/log/openvpn-status.log
log-append /var/log/openvpn.log
verb 3
EOF
クライアント設定ファイル作成
クライアントに配布する証明書(秘密鍵、公開鍵)を「/tmp/openvpn-client-key/config」に集めます。
mkdir -p /tmp/openvpn-client-key/config
cp /etc/openvpn/pki/ca.crt /tmp/openvpn-client-key/config
cp /etc/openvpn/pki/issued/client.crt /tmp/openvpn-client-key/config
cp /etc/openvpn/pki/private/client.key /tmp/openvpn-client-key/config
cp /etc/openvpn/ta.key /tmp/openvpn-client-key/config
また、クライアント側の設定ファイルは、内容は以下で、client.ovpnとして保存。クライアント側の設定ファイルをリモート参加者が書き換えしなくてもよいように、サーバの指定は、ホスト名にしました。NifmoはグローバルIPもらえるので、No-IPという無料のDynamic DNSで登録しました。
cat << EOF > /tmp/openvpn-client-key/config/client.ovpn
client
dev tun
proto tcp
remote 合宿地のホスト名.ddns.net 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
remote-cert-tls server
tls-auth ta.key 1
cipher AES-256-CBC
verb 3
EOF
「/tmp/openvpn-client-key/」に集めたファイル群をzipとかで固めてリモート参加者に渡します。(お約束の文言ですが、、安全な経路で渡しましょう。渡したファイルは適切に管理してもらいましょう。)
ルーティング設定
VPNはtunデバイスなので、L3ルーティング設定が必要。iptablesでVPN側とLAN側を相互にルーティングさせます。OpenWrtの場合、/etc/firewall.userにiptablesのコマンドを記述しておけば読み込んでくれるみたいです。
cat << EOF > /etc/firewall.user
iptables -I FORWARD -i br-lan -o tun0 -s 192.168.249.0/24 -d 10.8.0.0/24 -m conntrack --ctstate NEW -j ACCEPT
iptables -I FORWARD -i tun0 -o br-lan -s 10.8.0.0/24 -d 192.168.249.0/24 -m conntrack --ctstate NEW -j ACCEPT
EOF
/etc/init.d/firewall restart
AndroidでUSBテザリング
OpenWrt側のドライバのインストール。
公式サイトの手順。ドライバいれて、usb0デバイスをDHCPクライアントに設定にする。
opkg update
opkg install kmod-usb-net-rndis
uci set network.usb0=interface
uci set network.usb0.ifname='usb0'
uci set network.usb0.proto='dhcp'
uci commit
/etc/init.d/network restart
Android側の設定
[設定]→「ネットワークとインターネット」→「アクセスポイントとテザリング」→「USBテザリング」をON
OpenWrt側で「usb0」デバイスが生えていれば成功。IPアドレスはランダムに決まる模様。
OpenWrt側に割り当たったIPアドレスはあとでAndroidのポートフォワードアプリで使うので記録しておく。下記の例では、「192.168.182.10」。テザリングのON/OFFで毎回IPアドレスが変わってしまうので若干面倒だが、起動後に一度確認するだけなので、ここは我慢・・・。
root@OpenWrt:~# ip a
(略)
11: usb0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN qlen 1000
link/ether f6:b4:61:10:16:d9 brd ff:ff:ff:ff:ff:ff
inet 192.168.182.10/24 brd 192.168.182.255 scope global usb0
valid_lft forever preferred_lft forever
inet6 fe80::f4b4:61ff:fe10:16d9/64 scope link
valid_lft forever preferred_lft forever
Androidでポートフォワードアプリをインストールと設定
今回は、AndroidでUSBテザリングして、OpenVPNの1194ポートをOpenWrt側にポートフォワードする構成にしますので、Androidでポートフォワードアプリをインストールします。
Fwdというアプリです。リンク
アプリ起動して、「+」ボタンで設定追加。設定内容は、以下にする。
名前は適当、Protocolは、tcp、fromは、rmnet_data2、ポートは、1194targetには、OpenWrt側のusb0のアドレス(192.168.182.10)を入れて、右上の「SAVE」を押して、「START」で開始
LTE側のIPアドレス確認とDynamic DNSの書き換え
今回、AndroidのLTE側に割り当たったのIPアドレスを確認する必要があったので、「PingTools Network Utilities」というアプリを使いました。リンク
Wi-FiをOFFにして起動すれば、LTE側のIPアドレスを確認できます。
確認したIPアドレスをNo-IPにログインして、Dynamic DNSの書き換え
合宿地側のPCにリモート側のルート設定追加
リモート側のセグメント(10.8.0.0/24)へのルート設定が必要なので。コマンドプロンプト開いて、
route -p add 10.8.0.0/24 mask 255.255.255.0 192.168.249.220
(上記の手順でもいいですが、今回は、別のWi-Fiルータもあり、そいつがDHCPサーバにもなっていたので、DHCPの設定でデフォルトゲートウェイを「192.168.249.220」に向けてしまいました。)
クライアント側の準備
- OpenVPNクライアントをダウンロード(OpenVPN-2.5.0-I601-amd64.msi)してインストール
- リモート参加者に配布した「openvpn-client-key.zip」を展開し、「c:\users[ログインユーザ名]\OpenVPN\config」にコピー
下記のフォルダ構造にする。
C:\USERS\[ログインユーザ名]\OPENVPN
├─config\
│ ca.crt
│ client.crt
│ client.key
│ client.ovpn
│ ta.key
│
└─log
- 合宿地側から準備OKの連絡がきたら、OpenVPN GUIを起動し、タスクトレイのOpenVPN GUIアイコンを
右クリックし「接続」をクリック。緑色のアイコンになったら接続完了
#最初の起動で「No readable connection・・・・」とメッセージがでてもそのまま「OK」を押す - pingで合宿地側のIPから応答があって、ゲームにログインできたらOK!
まとめ
TL-WR902ACで旅先VPNサーバをつくりました。旅先なのでAndroid端末でテザリングしましたが、家庭のルータでも同じことできそう。以上。
おまけ
元のファームに戻す手順
dd if="TL-WR902ACv3_JP_0.9.1_0.2_up_boot[191209-rel55646].bin" of=tp_recovery.bin skip=257 bs=512
- tp_recovery.binをscpでTL-WR902ACに転送。転送先は、RAMDISKの/tmpへ。
scp tp_recovery.bin root@192.168.1.1:/tmp
- 「mtd」コマンドで元ファームを書き込み。完了すると自動で再起動します。
mtd -r write /tmp/tp_recovery.bin firmware
Unlocking firmware ...
Writing from /tmp/tp_recovery.bin to firmware ...
Rebooting ...