1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

wsl2でsshuttle - winでssh先に簡易VPNを張る

Last updated at Posted at 2020-08-23

wsshuttle

WSL2 から手軽に sshuttle を行う wsshuttle を作ったので、お試しください。

インストール
sudo apt install -y ipcalc
pip3 install sshuttle # apt によってインストールされるものはバージョンが古くて動かない可能性がある
sudo wget https://raw.githubusercontent.com/yabeenico/wsshuttle/main/wsshuttle -O /usr/local/bin/wsshuttle
sudo chmod +x /usr/local/bin/wsshuttle
実行例
# ルーティングテーブルを変更するため、実行する WSL2 のターミナルに Windows の admin 権限が必要。
wsshuttle -r ssh-server -x 157.0.0.0/8 0/0
dry-run
wsshuttle -r ssh-server -x 157.0.0.0/8 0/0 --dry
route.exe delete 157.0.0.0 mask 255.0.0.0
route.exe delete 3.3.3.3   mask 255.255.255.255
route.exe delete 0.0.0.0   mask 128.0.0.0
route.exe delete 128.0.0.0 mask 128.0.0.0
route.exe add    157.0.0.0 mask 255.0.0.0       192.168.3.1    metric 1 if 7
route.exe add    3.3.3.3   mask 255.255.255.255 192.168.3.1    metric 1 if 7
route.exe add    0.0.0.0   mask 128.0.0.0       172.18.187.223 metric 1 if 46
route.exe add    128.0.0.0 mask 128.0.0.0       172.18.187.223 metric 1 if 46
sshuttle -l 0.0.0.0:0 -x 3.3.3.3 -r ssh-server -x 157.0.0.0/8 0/0
route.exe delete 157.0.0.0 mask 255.0.0.0
route.exe delete 3.3.3.3   mask 255.255.255.255
route.exe delete 0.0.0.0   mask 128.0.0.0
route.exe delete 128.0.0.0 mask 128.0.0.

要約

外出先 win から 自宅 NW に VPNを張りたい。
コマンドは管理者権限を持った wsl2 で実行。

  • インストール
sudo apt install -y sshuttle ipcalc
  • env: 環境変数を設定
export IF_WIN_MAC=XX-XX-XX-XX-XX-XX # 手動で設定: win の 物理 NIC の MAC アドレス
export HOME_NW=192.168.3.0/24 # 手動で設定: 自宅の NW (LAN)
export HOME_GIP=$(ssh ssh-server curl inet-ip.info 2>/dev/null) # もしくは手動で設定

export HOME_NW_ADDR=$(ipcalc $HOME_NW | grep ^Address | awk '{print $2}')
export HOME_NW_MASK=$(ipcalc $HOME_NW | grep ^Netmask | awk '{print $2}')
export IF_WIN_IDX=$(route.exe print | grep -i "$(echo $IF_WIN_MAC | perl -pe 's/-/ /g')" | awk -v FS=. '{print $1}' | sed 's/ //g')
export IF_WIN_IP=$(arp.exe -a | grep ^Interface | grep $(printf %x $IF_WIN_IDX) | awk '{print $2}')
export VIF_WIN_IP=$(grep -o '172.*' /etc/resolv.conf)
export VIF_WIN_IDX=$(arp.exe -a | grep ^Interface | grep $VIF_WIN_IP | awk '{print $4}' | perl -pe '$_=hex')
export VIF_WSL2_IP=$(hostname -I)
$ env | egrep 'IF_W|HOME_' | sort
HOME_GIP=30.30.30.30
HOME_NW=192.168.3.0/24
HOME_NW_ADDR=192.168.3.0
HOME_NW_MASK=255.255.255.0
IF_WIN_IDX=21
IF_WIN_IP=10.0.0.2
IF_WIN_MAC=XX-XX-XX-XX-XX-XX
VIF_WIN_IDX=33
VIF_WIN_IP=172.21.48.1
VIF_WSL2_IP=172.21.49.46
  • lan: 宛先が 192.168.3.0/24 のパケットのみをトンネリング。
route.exe add $HOME_NW_ADDR mask $HOME_NW_MASK $VIF_WSL2_IP metric 1 if $VIF_WIN_IDX
sshuttle -r ssh-server -l 0 $HOME_NW
  • global: 全てのパケットをトンネリング。
route.exe delete 0.0.0.0
route.exe add $HOME_GIP mask 255.255.255.255 $IF_WIN_IP metric 1 if $IF_WIN_IDX
route.exe add 0.0.0.0 mask 0.0.0.0 $VIF_WSL2_IP metric 2 if $VIF_WIN_IDX
sshuttle -r user@$HOME_GIP:22 -l 0 0/0 -x $HOME_GIP # ssh 接続先は適宜設定 (ドメインの名前解決は不可)
  • default: VPN を解除。
route.exe delete 0.0.0.0
route.exe add 0.0.0.0 mask 0.0.0.0 $IF_WIN_IP metric 1 if $IF_WIN_IDX

目的

外出先 win から自宅の NW (192.168.3.0/24) に簡易 VPN を張る (画像を参照)。
以下、lan と global の2パターンについて解説する。

  • lan: 宛先が 192.168.3.0/24 のパケットのみをトンネリング。
    • 外出先 win から curl.exe 192.168.3.2 を叩いて結果を得る。 (or ブラウザで 192.168.3.2 を開く)
  • global: 全てのパケットをトンネリング。
    • 外出先 win から curl.exe inet-ip.info (グローバル IP 取得) を叩いて 30.30.30.30 の結果を得る。

image.png

手順

  1. 図の routing: route.exe を利用し、 win が送信するパケットを wsl2 を迂回するように、 win のルーティングテーブルを設定する。 (wsl2 のシェルを管理者権限で実行する必要あり)
  2. 図の shuttle: sshuttle を利用し、 wsl2 から ssh 接続可能な NW に対して簡易 VPN を張る。

解説

  • wsl2 は、図に示すとおり、ゲスト OS とホスト OS が仮想 NW で接続される。
    • VIF_WIN、VIF_WSL2 は、その仮想 NWに接続された仮想 NIC。
    • IF_WIN は、win の物理 NIC。
  • route.exe add 192.168.3.0 mask 255.255.255.0 172.21.49.46 metric 1 if 33
    • 宛先が 192.168.3.0/24 のパケットを、NIC インデックス == 33 の NIC から 172.21.49.46 に向けて転送。
    • metric は優先度。小さいほど優先度が高い。
  • sshuttle -r ssh-server -l 0 192.168.3.0/24 -x 192.168.3.100
    • 宛先が 192.168.3.0/24 のパケットを ssh-server 経由でトンネリング。
    • ただし、宛先が 192.168.3.100 のパケットはトンネリングしない。
    • -l 0-l 0.0.0.0/0.0.0.0 の略で、全ての送信元のパケットを許可。

実用的なスクリプト

要旨に記述したコマンドに初期化処理や後始末を付け加えたもの。

check.sh

VPN が機能しているかを確認する、

  • グローバル IP の確認
    • 20.20.20.20: 外出先
    • 30.30.30.30: 自宅
  • web-server (192.168.3.2) への疎通確認
check.sh
#!/bin/bash

curl     inet-ip.info
curl     -sS --connect-timeout 1 192.168.3.2 | head -n 1

curl.exe inet-ip.info
curl.exe -sS --connect-timeout 1 192.168.3.2 | head -n 1

env.sh

env.sh
#!/bin/bash

export IF_WIN_MAC=XX-XX-XX-XX-XX-XX # 手動で設定: win の 物理 NIC の MAC アドレス
export HOME_NW=192.168.3.0/24 # 手動で設定: 自宅の NW (LAN)
export HOME_GIP=$(ssh ssh-server curl inet-ip.info 2>/dev/null) # もしくは手動で設定

export HOME_NW_ADDR=$(ipcalc $HOME_NW | grep ^Address | awk '{print $2}')
export HOME_NW_MASK=$(ipcalc $HOME_NW | grep ^Netmask | awk '{print $2}')

export IF_WIN_IDX=$(route.exe print | grep -i "$(echo $IF_WIN_MAC | perl -pe 's/-/ /g')" | awk -v FS=. '{print $1}' | sed 's/ //g')
export IF_WIN_IP=$(arp.exe -a | grep ^Interface | grep $(printf %x $IF_WIN_IDX) | awk '{print $2}')

export VIF_WIN_IP=$(grep -o '172.*' /etc/resolv.conf)
export VIF_WIN_IDX=$(arp.exe -a | grep ^Interface | grep $VIF_WIN_IP | awk '{print $4}' | perl -pe '$_=hex')
#export VIF_WIN_IP=$(arp -a | awk -v FS='[()]' '{print $2}' | sort | head -n 1)

export VIF_WSL2_IP=$(hostname -I)
$ source env.sh
$ env | egrep 'IF_W|HOME_' | sort
HOME_GIP=30.30.30.30
HOME_NW=192.168.3.0/24
HOME_NW_ADDR=192.168.3.0
HOME_NW_MASK=255.255.255.0
IF_WIN_IDX=21
IF_WIN_IP=10.0.0.2
IF_WIN_MAC=XX-XX-XX-XX-XX-XX
VIF_WIN_IDX=33
VIF_WIN_IP=172.21.48.1
VIF_WSL2_IP=172.21.49.46

default.sh

VPNを解除。

default.sh
#!/bin/bash

source env.sh
# set -x

route.exe delete $HOME_GIP
route.exe delete $HOME_NW_ADDR

route.exe delete 0.0.0.0
route.exe add 0.0.0.0 mask 0.0.0.0 $IF_WIN_IP metric 1 if $IF_WIN_IDX
$ ./default.sh # set -x をアンコメントして実行した結果
+ route.exe delete 30.30.30.30
The route deletion failed: Element not found.

+ route.exe delete 192.168.3.0
The route deletion failed: Element not found.

+ route.exe delete 0.0.0.0
 OK!

+ route.exe add 0.0.0.0 mask 0.0.0.0 172.28.100.51 metric 1 if 21
 OK!
$ ./check.sh
20.20.20.20
curl: (28) Connection timed out after 1001 milliseconds
20.20.20.20
curl: (28) Connection timed out after 1000 milliseconds

グローバル IP が外出先 (20.20.20.20) かつ、web-server とも疎通していない。

lan.sh

宛先が HOME_NW == 192.168.3.0/24 のパケットのみをトンネリング。

lan.sh
#!/bin/bash

source env.sh
set -x

./default.sh &>/dev/null

route.exe add $HOME_NW_ADDR mask $HOME_NW_MASK $VIF_WSL2_IP metric 1 if $VIF_WIN_IDX
sshuttle -r ssh-server -l 0 $HOME_NW

./default.sh &>/dev/null
$ ./lan.sh
+ ./default.shl
+ route.exe add 192.168.3.0 mask 255.255.255.0 172.21.49.46 metric 1 if 33
 OK!
+ sshuttle -r ssh-server -l 0 192.168.3.0/24
client: Connected.
^Cclient:
client: Keyboard interrupt: exiting.
+ ./default.sh
$ ./check.sh # sshuttle 実行中に別のシェルで実行
20.20.20.20
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
20.20.20.20
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">

グローバル IP は外出先 (20.20.20.20) だが、web-serverとは疎通している。

global.sh

全てのパケットをトンネリング。

global.sh
#!/bin/bash

source env.sh
set -x

./default.sh &>/dev/null

route.exe delete 0.0.0.0

route.exe add $HOME_GIP mask 255.255.255.255 $IF_WIN_IP metric 1 if $IF_WIN_IDX
# 宛先が HOME_GIP (30.30.30.30) のパケットは例外として、物理 NIC (IF_WIN_IDX == 21) から送信する。

route.exe add 0.0.0.0 mask 0.0.0.0 $VIF_WSL2_IP metric 2 if $VIF_WIN_IDX
# 上記例外以外の全てのパケットは win の 仮想 NIC (VIF_WIN_IDX == 33) 経由で WSL2 の 仮想 NIC (VIF_WSL2_IP == 172.21.49.46) に転送。

sshuttle -r user@$HOME_GIP:22 -l 0 0/0 -x $HOME_GIP
# 全てのパケットをトンネリング。
# ただし、宛先が HOME_GIP (30.30.30.30) のパケットを除く。
# HOME_GIP をトンネリング対象から除外しないと、HOME_GIP に ssh 接続できなくなる。
# また、名前解決の問い合わせパケットもやり取りできなくなるため、ssh の接続先は IP アドレス直打ちにする。

./default.sh &>/dev/null
$ ./global.sh
+ ./default.sh
+ route.exe delete 0.0.0.0
 OK!
+ route.exe add 30.30.30.30 mask 255.255.255.255 172.28.100.51 metric 1 if 21
 OK!
+ route.exe add 0.0.0.0 mask 0.0.0.0 172.21.49.46 metric 2 if 33
 OK!
+ sshuttle -r user@30.30.30.30:22 -l 0 0/0 -x 30.30.30.30
client: Connected.
^Cclient:
client: Keyboard interrupt: exiting.
+ ./default.sh
$ ./check.sh # sshuttle 実行中に別のシェルで実行
30.30.30.30
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
30.30.30.30
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">

グローバル IP が自宅 (30.30.30.30) かつ、web-server とも疎通している。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?