それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

OpenWrt で softether のVPN接続する、udhcpdによるIP取得とルーティングする

openWrt で softetherVPNをルーティングする

openwrt に vpn 拠点間接続をやらせてみる

リモート側のネットワークの設定やマスカレードなどは済んでいる状態。OpenWRTからリモートへ接続する

Host-->openwrt--<SoftEtherVPN>--VPN Server--(office network)--10.193.3.40

細かいことは抜いておいて、相手先のネットワークのサーバーにアクセスできればいい。

openwrt に softether のクライアントを入れる

opkg install softethervpn-client

vpnclientvpncmd が導入される。

インストールするとClientが起動している

localhostSoftEther のクライアントが起動している。起動を確認しておく。

root@OpenWrt:~# ps auxf | grep softethervpn
root      2116  0.0  0.0   6644  1600 ?        S<s  03:48   0:00 /usr/libexec/softethervpn/vpnclient execsvc
root      2119  0.9  0.1  23000 16528 ?        S<l  03:48   0:02  \_ /usr/libexec/softethervpn/vpnclient execsvc

SoftEtherの設定 vpncmd

このあたりはmacOS/Ubuntu で接続するときと同じ

vpncmd /CLIENT localhost /CMD NicCreate
vpncmd /CLIENT localhost /CMD AccountList
vpncmd /CLIENT localhost /CMD AccountCreate
vpncmd /CLIENT localhost /CMD AccountPasswordSet
vpncmd /CLIENT localhost /CMD AccountConnect ocn
vpncmd /CLIENT localhost /CMD AccountList
コマンド 設定値
NicCreate soeth0
AccountCreate /name:ocn /nic:soeth0 /hub=Vpn /remote=vpn.my-office.jp:443
AccountPasswordSet パスワード

上記のとおりにコマンドをいれてもいいが、毎回毎回訊かれるのが面倒。

コマンドの引数を使ってコピペ可能にする。

## 共通化
alias vpncmd='vpncmd /CLIENT localhost /CMD ' # コマンド省略
conn=ocn-tak # 接続名
## 接続作成
vpncmd NicCreate soeth0
vpncmd AccountCreate $conn /SERVER:vpn.ocn.ac.tld:443 /USERNAME:takuya1234 /HUB:USER_HUB /NICNAME:vpn_soeth0
vpncmd /CLIENT localhost /CMD AccountPasswordSet $conn  /PASSWORD:mypassword /TYPE:radius

## 接続と確認
vpncmd /CLIENT localhost /CMD AccountConnect  $conn
vpncmd /CLIENT localhost /CMD AccountList 
vpncmd /CLIENT localhost /CMD AccountStatusGet $conn
## 切断と確認
vpncmd /CLIENT localhost /CMD AccountDisConnect  $conn
vpncmd /CLIENT localhost /CMD AccountList 
vpncmd /CLIENT localhost /CMD AccountStatusGet $conn

接続すると、Nicの名前に vpn_プレフィックスされたインターフェイスが現れる。

今回は、Nic の名前を soeth0 としたので、 vpn_soeth0 が出現する。

dhcpでアドレスを取得

openwrt の場合、udhcp を使えばいいので、それ用のスクリプトを用意する。

アドレス取得時に、最低限のルーティングを行うのだが

最初は動作確認のために、ルーティングは書かずにアドレスだけもらっておく。

ルーティングは動作確認後に後で追記する。

etc/config/custom/softether/dhcp.sh(ルーティングなし)

#!/usr/bin/env bash

setup_interface() {
  echo "udhcpc: ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+}"
  ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+}
    # info
  echo router=${router}
  
}
case "$1" in
  deconfig)
    ifconfig "$interface" 0.0.0.0
    ;;
  renew)
    setup_interface update
    ;;
  bound)
    setup_interface ifup
    ;;
esac

udhcp でアドレス取得

これで、IPアドレスが取得される。

udhcpc -i vpn_soeth0 -s /etc/config/custom/softether/dhcp.sh

ルーティング

仮想Hub経由してルータに接続する。

ping 10.35.225.254

ルータに接続できたら、GWとして、ルーティングを入れてやる。

ip route add 10.193.3.0/24 via 10.35.225.254 dev vpn_soeth0

ルーティングテーブル追加の確認。pingで接続を確認する。

ping 10.193.3.40

これで、OpenWRTから、リモート側のPCまで到達できた。

VPN接続を共有する(マスカレード)

OpenWRTにルータらしく、NATとマスカレードをして、ローカル側にVPN接続を共有させる。

要は、マスカレードとフォワーディングを入れてやる。

VPN_IF=vpn_soeth0
iptables -I FORWARD -o $VPN_IF -j ACCEPT
iptables -t nat -A POSTROUTING -o $VPN_IF -j MASQUERADE

共有を確認する

192.168.1.100 から 10.193.3.40へ接続を確認する

takuya@work $ ssh 192.168.1.100 
takuya@192.168.1.100 $ ping 10.193.3.40

パケットが応答されたので、接続できた。

設定を永続化する。

最後に、udhcp の起動スクリプトに、これらのルーティングを書き加える。

etc/config/custom/softether/dhcp.sh(ルーティング追加)

#!/usr/bin/env bash

setup_interface() {
  echo "udhcpc: ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+}"
  ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+}
    ### 追加
  # routing
  ip route add 10.193.3.0/24 via ${router} dev ${interface}
  # masquerade
  iptables -I FORWARD -o ${interface} -j ACCEPT
  iptables -t nat -A POSTROUTING -o ${interface} -j MASQUERADE
}

case "$1" in
  deconfig)
    ifconfig "$interface" 0.0.0.0
    ;;
  renew)
    setup_interface update
    ;;
  bound)
    setup_interface ifup
    ;;
esac

動作チェックする。

## iptables を初期化して
service firewall restart
## ip を解放してルーティング・テーブルをリセット
ifconfig vpn_soeth0 0.0.0.0
## softether を切断
vpncmd /CLIENT localhost /CMD AccountDisConnect ocn

## softethre を接続
vpncmd /CLIENT localhost /CMD AccountConnect ocn
## dhcp 取得とルーティング設定
udhcpc -i vpn_soeth0 -s /etc/config/custom/softether/dhcp.sh

接続を切断して、再接続し、dhcp を再取得、udhcが指定スクリプトを動かす。

udhcp が取得後に、指定スクリプトを実行して、ipアドレス設定とルーティングを設定コマンドを流してくれる。

この一連の流れをコマンド化

/etc/config/custom/softether/start-my-softether-connection.sh

vpncmd /CLIENT localhost /CMD AccountDisConnect ocn
vpncmd /CLIENT localhost /CMD AccountConnect ocn
udhcpc -i vpn_soeth0 -s /etc/config/custom/softether/dhcp.sh

udhcpc の接続をrenew/releaseする

udhcpc は常駐させるモードと常駐させないモードが有る。

udhcpc -S -C -i $VPN_IF -s $UDHCP_SCRIPT        # プロセスが常駐する
udhcpc -q -S -C -i $VPN_IF -s $UDHCP_SCRIPT    # 実行したら終わり。プロセスは常駐しない。

プロセスを常駐している場合、シグナルで、renew/releaseが可能になる。

## dhcp を renew する
 pkill -USR1 -f "udhcpc -S -C -i $VPN_IF -s $UDHCP_SCRIPT"
## dhcp を release する
 pkill -USR2 -f "udhcpc -S -C -i $VPN_IF -s $UDHCP_SCRIPT"

それぞれ、終了後にスクリプト実行して、ルーティングなどの処理を追加することができる。

割当解放(リリース)した場合は /bin/sh $UDHCP_SCRIPT deconfig が呼ばれ、割当更新(renew)した場合は、/bin/sh $UDHCP_SCRIPT renew がそれぞれの引数(deconfig , renew, bound )をつけて実行される。

この引数を使ってdhcp割当・解放・更新のスクリプトを書くことができる。

スクリプト

# router, interface ip の変数はudhcpcから渡される
function cleanup_interface(){
  ## ルーティング解放・IP割当解除などの処理
 nft del table my_vpn
  ip route del ${DEST_NET} via ${router} dev ${interface} 
  ifconfig $interface 0.0.0.0
}
function setup_interface (){
  ## IP割当処理、ルーティング作成などの処理
  ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+}
  ip route add ${DEST_NET} via ${router} dev ${interface} 
  nft add table my_vpn
}

case "$1" in

  deconfig)
    cleanup_interface
    ;;
  renew)
    setup_interface update
    ;;
  bound)
    setup_interface ifup
    ;;

esac

常駐している場合にシグナルを受け取って片付けのdeconf 処理を書くことができる。

pppoe 接続時にSoftEtherVPN接続を起動する

ppooe 接続時にスクリプトを動かすには、hotplug.d を使えばいいので、hotplug で実行するスクリプトを作る。

PPPoEが起動したら、間髪入れず、SoftEther を接続しに行くようにする。

/etc/hotplug.d/iface/99-softether

#!/usr/bin/env bash
## PPPoE接続後に、 スクリプトを実行する
## iface の変化後に、TARGET_INTERFACEで検出して任意のフックが可能
## main
function main(){
  TARGET_INTERFACE=pppoe-XXX
  TARGET_DEVICE=eth1
  ###
  [ "$ACTION" = "ifup" -a "$INTERFACE" = "$TARGET_INTERFACE"  ] && {
    # log sample
    logger "iface $TARGET_INTERFACE / $TARGET_DEVICE up detected, do hotplug actions."
    sleep 10;
        /etc/config/custom/softether/start-my-softether-connection.sh   
    }
}
main

最後の最後に、再接続チェック

ネットワークを再起動して、pppoe接続後にsoftether がちゃんと接続されて、ルーティングとマスカレードされることを確認する。

root#openWrt $ service network restart

注意点

実験用openWrt ルータはx86/ext4 で動作しているので、パッケージを容量気にせずに入れている。

bash / iproute2 / iptables-full など割と大きめのパッケージを入れて、そのへんのubuntu とおなじような動作しているので、容量がシビアなwrt だとこの方法だとうまくイカないかもしれない。

2023-08-29 追記

接続コマンドと作成コマンドをダイアログではなくコマンド引数で与えるようにメモを更新。

2023-08-30 追記

udhcpc の使い方が足りなかったので調査して追記。

参考資料