Quantcast
Channel: Bashタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 2808

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

$
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)
  • 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/bashexport 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-vFS=.'{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/bashsource 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/bashsource 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 yb -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/bashsource 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 とも疎通している。


Viewing all articles
Browse latest Browse all 2808

Trending Articles