それマグで!

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

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

wireguardのvpn をwg-quickを抜きで作ってみる。(ip6tablesなどの細かい設定を制御してv6NATしたい)

wireguard vpn を手作業で作る

openwrt がv6のアドレスに対して wireguard を作成すると、インタフェースの設定ではなぜかエラーになったので、手作業でコマンドを打ち込んでwireguard を起動する必要があってめんどくさかった。wg-quick もそのままインストールできないし。

マニュアルで接続する

wg-quick がないときに、手作業(マニュアル)でwg0のインターフェイスを定義して、そこをWireguardを使ってVPNを接続する。

最初に受け付ける側(サーバー動作)

wireguardはサーバとクライアントの区別が曖昧なので、明確にサーバーと呼べないと思われる。

最初に、接続受けつける側で受け付けられる用に設定を作っていく。

既存の削除

ip link set wg0 down
ip link delete dev wg0

インターフェースの作成

インターフェイスを作成して、IPアドレスを割り当てる。

ip link add dev wg0 type wireguard
ip addr add 172.16.3.2/32 dev wg0

ポートとプライベートキーの設定

どのポートでリッスンするかを決める。リッスンポートは決められるがリッスンするインターフェイスは決められない。

ポートは自由に決められる。iOSのソフトウェアやwireguardのマニュアルは 51821 を使っているのでそれに倣う。

wg set wg0 listen-port 51821 \
private-key /etc/config/custom/wireguard/wg0.server.key 

peer 接続

さらにサーバー側に、peer 間接続で使う設定を入れる。

wg set wg0 \
 peer UF52AMi4xLFYHN21XVcZUnDmuYY6xriM3TyAOrmNTHE=\
 preshared-key   /etc/config/custom/wireguard/wg_psk.psk\
 endpoint 2xxx:xxx:8383:a300:5054:ff:fxxx:xxxx:51821\
 allowed-ips 172.16.3.1/32

次のクライアントのを接続を受け付けますよ。という設定をする。

接続可能なクライアントの設定という体になる。 peer 同士が接続するのでサーバーとクライアントの明確な区別はないのだが。便宜上。

クライアント側も同様にしておく。

同様の設定を peerの両端に行う。

開始

ip link set wg0 up

必要に応じて routing を設定する。

172.16.3.1/32 側(今回のサーバー側で、クライアント側への経路)

ip route add 172.16.3.2/32 dev wg0

172.16.3.2/32 側(今回のクライアント側で。サーバー側への経路)

ip route add 172.16.3.1/32 dev wg0

覚えにくいのでスクリプトにまとめる。

シンプルとはいえ、手順は多いので、スクリプトにwg0 の作成と接続とルーティングをまとめて行うスクリプトをを作っておいた。

wireguard の 手順がわかりやすくなった。

出来上がった実行スクリプト

/etc/config/custom/wireguard/wg0-start.sh

#!/bin/bash

# ## LOCAL
# WG_IF=wg0
# WG_PORT=51821
# WG_LOCAL_LISTEN_PORT=$WG_PORT
# WG_LOCAL_IPv4=172.16.3.2/24
# WG_LOCAL_IPv6=fd00:baba:afac:4610::2/64
# WG_LOCAL_v4_NETADDR="${WG_LOCAL_IPv4%.*}.0/24"
# WG_LOCAL_v6_NETADDR="${WG_LOCAL_IPv6%:*}::/64"
#
# CONFIG_PATH=/etc/config/custom/wireguard/$WG_IF
#
# ## 秘密鍵
# WG_LOCAL_SECRETKEY_PATH=$CONFIG_PATH/secret.key
#
# ## PEER 設定
# WG_PEER_PUBKEY=$(cat $CONFIG_PATH/peer.pub)
# WG_PEER_PSK_PATH=$CONFIG_PATH/peer.psk
# WG_PEER_KEEPALIVE=60
# WG_PEER_ENDPOINT_IP=
# WG_PEER_ENDPOINT_PORT=$WG_PORT
# WG_PEER_ENDPOINT=$WG_PEER_ENDPOINT_IP:$WG_PEER_ENDPOINT_PORT
# ## 対向IPアドレス
# WG_PEER_IPv4="${WG_LOCAL_IPv4%.*}.1/24"
# WG_PEER_IPv6="${WG_LOCAL_IPv6%:*}:1/64"
# ## wg0ネットワークアドレス
# WG_PEER_IPv4_NET_ADDR=$WG_LOCAL_v4_NETADDR
# WG_PEER_IPv6_NET_ADDR=$WG_LOCAL_v6_NETADDR
# ## 転送をするリモートネットワーク
# REMOTE_NETWORK=( 192.168.2.0/24 192.168.100.0/24 )
# ENABLE_ROUTING=1
# ENABLE_DEFAULT_GW=1


WG_NATv6_ENABLED=1


function restart(){
  stop;start;
}
function stop(){
  ## 既存の削除
  if ip link show  $WG_IF 1>/dev/null  2>&1  ; then
    ip link set $WG_IF down
    ip link delete dev $WG_IF
  fi
}
function start_wg(){
  ## 既存の削除
  if ip link show  $WG_IF 1>/dev/null  2>&1  ; then
    echo already up.
    return 0;
  fi
  ## v6 経由の経路を追加しとく
  set_NTTflets_NGN_route;

  # インターフェースの作成
  ip link add dev $WG_IF type wireguard
  ip addr add $WG_LOCAL_IPv4 dev $WG_IF
  ip addr add $WG_LOCAL_IPv6 dev $WG_IF
  ip link set mtu 1420 up dev $WG_IF


  # ポートとプライベートキーの設定
  cmd="wg set $WG_IF listen-port $WG_LOCAL_LISTEN_PORT \
   private-key $WG_LOCAL_SECRETKEY_PATH"
  #echo $cmd
  $cmd;
  # 開始
  ip link set $WG_IF up

}
function add_peer(){
  ## peer 接続
  cmd="wg set wg0
   peer $WG_PEER_PUBKEY
   preshared-key   $WG_PEER_PSK_PATH
   persistent-keepalive $WG_PEER_KEEPALIVE
   allowed-ips $WG_PEER_IPv4_NET_ADDR,$WG_PEER_IPv6_NET_ADDR,$(IFS=,; printf '%s' "${REMOTE_NETWORK[*]}")
   "
  if [[ ! -z $WG_PEER_ENDPOINT ]]; then
    cmd="$cmd endpoint $WG_PEER_ENDPOINT ";
  fi
  # 実行
  # echo $cmd
  $cmd;

  ## 経路作成
  allow_forwardings_v4
  #allow_forwardings_v6
  add_route

}
function start(){
  ## wg接続を開始
  start_wg;

  ## peer を作成
  add_peer


}

function allow_forwardings_v6(){
  enable_v6_forwarding
  allow_v6_forwarding
}
function allow_v6_forwarding(){

  echo WG_NATv6_ENABLED=$WG_NATv6_ENABLED
  if [[ -z $WG_NATv6_ENABLED  ]] ; then
    ip6tables -I INPUT   -i $WG_IF -j ACCEPT
    ip6tables -I FORWARD -i $WG_IF -j ACCEPT
    ip6tables -I OUTPUT  -o $WG_IF -j ACCEPT
    ip6tables -I FORWARD -o $WG_IF -j ACCEPT
  else
    allow_v6_masquerade
  fi
}
function allow_v6_masquerade(){

  WG_IF=wg0
  NGN_IF=eth1
  LAN_IF=eth0

  DEFAULT_v6_GW=$( [[ $(ip neigh show dev $NGN_IF ) =~ (fe80[0-9a-f:]+) ]] ; echo ${BASH_REMATCH} )
  NGN_Adr=$([[ $(ip -6 addr show dev $NGN_IF ) =~ (2001|2400)[a-f0-9:/]+ ]]; echo $BASH_REMATCH)
  NGN_NAdr=${NGN_v6%:*:*:*:*}::/64

  WG_Adr=$([[ $(ip -6 addr show dev $WG_IF ) =~ fd([a-f0-9:]{1,4})+/[0-9]+ ]]; echo $BASH_REMATCH)
  WG_NAdr=$(owipcalc  $WG_Adr network)

  ## WG_IF → NGN へのNAT
  #echo ip6tables -A FORWARD -i $WG_IF  -o $NGN_IF -j ACCEPT
  #echo ip6tables -A FORWARD -i $NGN_IF -o $WG_IF  -j ACCEPT -m conntrack --ctstate RELATED,ESTABLISHED
  #echo ip6tables -t nat -A POSTROUTING -o $NGN_IF -d ::/0 -j MASQUERADE
  ip6tables -A FORWARD -i $WG_IF  -o $NGN_IF -j ACCEPT
  ip6tables -A FORWARD -i $NGN_IF -o $WG_IF  -j ACCEPT -m conntrack --ctstate RELATED,ESTABLISHED
  ip6tables -t nat -A POSTROUTING -o $NGN_IF -d ::/0 -j MASQUERADE
  ## LAN→ WG_IF へのNAT
  ip6tables -I FORWARD -i $WG_IF  -o $LAN_IF -j ACCEPT
  ip6tables -t nat -A POSTROUTING -o $WG_IF -d ::/0 -j MASQUERADE

}

function allow_forwardings_v4(){
  enable_v4_forwarding
  allow_v4_forwarding
}
function allow_v4_forwarding(){
  iptables -I INPUT   -i $WG_IF -j ACCEPT
  iptables -I FORWARD -i $WG_IF -j ACCEPT
  iptables -I OUTPUT  -o $WG_IF -j ACCEPT
  iptables -I FORWARD -o $WG_IF -j ACCEPT
}
function enable_v4_forwarding(){
  sysctl net.ipv4.conf.all.forwarding=1 > /dev/null
}

function enable_v6_forwarding(){
  sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
}
function add_route(){


  ip route add ${WG_PEER_IPv6%/*} from ${WG_LOCAL_IPv6%/*} dev $WG_IF metric 499 onlink

  if [[ $ENABLE_ROUTING != 1 ]]; then
    return;
  fi
  ## 例
  # 特定のIPだけ転送する場合。
  #   ip route add 192.168.100.5/32  dev $WG_IF via ${WG_PEER_IPv4%/*} onlink
  # ネットワーク転送する場合。
  #   ip route add 192.168.100.0/24  dev $WG_IF via ${WG_PEER_IPv4%/*} onlink
  for e in ${REMOTE_NETWORK[@]} ; do
    GATEWAY=''
    if [[ $e =~ : ]] ; then
      v6='-6'
      GATEWAY=${WG_PEER_IPv6%/*}
    else
      v6=''
      GATEWAY=${WG_PEER_IPv4%/*}
    fi
    if [[ $e == 0.0.0.0/0 && ! $ENABLE_DEFAULT_GW == 1 ]]; then
      return
    fi
    if [[ $e == ::/0 && ! $ENABLE_DEFAULT_GW == 1 ]]; then
      return
    fi

    echo ip route add $e  dev $WG_IF via $GATEWAY  metric 499 onlink
    ip route add $e  dev $WG_IF via $GATEWAY metric 499 onlink
  done
}
function set_NTTflets_NGN_route(){
  ## v6 の経路を明示的に指定したいとき
  ## わたしはNGNを壊れたまま運用。v6デフォルトGWを設定せずv6を壊してある。
  ## 特定のv6と通信するとき経路情報を都度入れている。
  /etc/config/custom/ipip6/v6_default_route.sh add $WG_PEER_ENDPOINT_IP
}





function main(){

  case $1 in
    start*)
      echo "start interface $WG_IF";
      start;
      ;;
    stop*)
      echo "stop interface $WG_IF";
      stop;
      ;;
     restart*)
      echo "restart interface $WG_IF";
      restart;
      ;;
    *)
      echo $0 'start|stop|restart';
      ;;

   esac

}

接続する側(クライアント)

#!/bin/bash


scripts=$(echo $(dirname $0)/../wg-start.sh)
source $scripts

## LOCAL
WG_IF=wg0
WG_PORT=51821
WG_LOCAL_LISTEN_PORT=$WG_PORT
WG_LOCAL_IPv4=172.16.3.1/24
WG_LOCAL_IPv6=fd00:baba:afac:4610::1/64
WG_LOCAL_v4_NETADDR="${WG_LOCAL_IPv4%.*}.0/24"
WG_LOCAL_v6_NETADDR="${WG_LOCAL_IPv6%:*}:/64"

CONFIG_PATH=/etc/config/custom/wireguard/$WG_IF

## 秘密鍵
WG_LOCAL_SECRETKEY_PATH=$CONFIG_PATH/secret.key

## PEER 設定
WG_PEER_PUBKEY=$(cat $CONFIG_PATH/peer.pub)
WG_PEER_PSK_PATH=$CONFIG_PATH/peer.psk
WG_PEER_KEEPALIVE=60
#### サーバー側ではendpoint は使わない
#### WG_PEER_ENDPOINT_IP=
#### WG_PEER_ENDPOINT_PORT=$WG_PORT
#### WG_PEER_ENDPOINT=$WG_PEER_ENDPOINT_IP:$WG_PEER_ENDPOINT_PORT
## 対向IPアドレス
WG_PEER_IPv4="${WG_LOCAL_IPv4%.*}.2/24"
WG_PEER_IPv6="${WG_LOCAL_IPv6%:*}:2/64"
## wg0ネットワークアドレス
WG_PEER_IPv4_NET_ADDR=$WG_LOCAL_v4_NETADDR
WG_PEER_IPv6_NET_ADDR=$WG_LOCAL_v6_NETADDR
## 転送をするリモートネットワーク
REMOTE_NETWORK=( 192.168.1.0/24 ::/0 )
##
ENABLE_ROUTING=1


##
main $@

接続を貰う側(サーバー)

#!/bin/bash


scripts=$(echo $(dirname $0)/../wg-start.sh)
source $scripts

## LOCAL
WG_IF=wg0
WG_PORT=51821
WG_LOCAL_LISTEN_PORT=$WG_PORT
WG_LOCAL_IPv4=172.16.3.2/24
WG_LOCAL_IPv6=fd00:baba:afac:4610::2/64
WG_LOCAL_v4_NETADDR="${WG_LOCAL_IPv4%.*}.0/24"
WG_LOCAL_v6_NETADDR="${WG_LOCAL_IPv6%:*}:/64"

CONFIG_PATH=/etc/config/custom/wireguard/$WG_IF

## 秘密鍵
WG_LOCAL_SECRETKEY_PATH=$CONFIG_PATH/secret.key

## PEER 設定(接続先)
WG_PEER_PUBKEY=$(cat $CONFIG_PATH/peer.pub)
WG_PEER_PSK_PATH=$CONFIG_PATH/peer.psk
WG_PEER_KEEPALIVE=60
WG_PEER_ENDPOINT_IP=2xxx:xxxx:a300:5054:ff:fea9:xxxxx
WG_PEER_ENDPOINT_PORT=$WG_PORT
WG_PEER_ENDPOINT=$WG_PEER_ENDPOINT_IP:$WG_PEER_ENDPOINT_PORT
## 対向IPアドレス
WG_PEER_IPv4="${WG_LOCAL_IPv4%.*}.1/24"
WG_PEER_IPv6="${WG_LOCAL_IPv6%:*}:1/64"
## wg0ネットワークアドレス
WG_PEER_IPv4_NET_ADDR=$WG_LOCAL_v4_NETADDR
WG_PEER_IPv6_NET_ADDR=$WG_LOCAL_v6_NETADDR
## 転送をするリモートネットワーク
REMOTE_NETWORK=( 192.168.2.0/24 192.168.100.0/24 ::/0 )
##
ENABLE_ROUTING=1


##
main $@

参考資料

https://qiita.com/fluo10/items/78e91884042645b08fb9