WireGuard with bridge interface?

色々調べてみてもWireGuardはLayer 3なのでTapデバイスは使えない。それゆえブリッジは無理っていう結論なのですが、調べてみるとなんとなくできそうなサイトが見つかりました。

GRE tunneling adds an additional GRE header between the inside and outside IP headers. In theory, GRE could encapsulate any Layer 3 protocol with a valid Ethernet type, unlike IPIP, which can only encapsulate IP.

An introduction to Linux virtual interfaces: Tunnels

2つのネットワークを同一ネットワークとして使うにはTunデバイスではなくTapデバイスを使います。WireGuardではTapデバイスが使えないのですが、サイトによると鍵はGRETAPを使うことです。そこが少し混乱するのですがIPv6で動くようです。これを使うにはカーネルモジュールのbr_netfilterをブート時にロードしておく必要があります。私のルーターで調べてみると、

br_netfilter           28672  0
bridge                233472  1 br_netfilter
ipv6                  622592  77 bridge,br_netfilter,wireguard

このようになっておりIPv6にbr_netfilterがリンクしています。そのあとはWireGuardのwg0.confでタップデバイスを立ち上げてブリッジインターフェースにリンクするという方法をとります。

PostUp = ip link add name gretap1 type gretap local 192.168.92.1 remote 192.168.178.1 
PostUp = ip link set gretap1 up
PostUp = ip link set gretap1 master br0

Tinc VPNではTapデバイスが使えるので簡単に同じネットワーク同士を繋ぐことができるのですが、WireGuardでも同様のことができるかもしれません。

OpenWrt

この情報をもとに早速OpenWrtで試してみました。機種はなんでも良いのですが先日、大量生産したOpenWrt化したfon2405eがあるのでそれを使いました。なかなか思うようにいかずOpenWrtのフォーラム等で検索して何度かトライしたらできました。

まずは802.11sの暗号なしのメッシュネットワークを作ります。次にWireGuardのネットワークを作ります。この時問題なのがWireGuardの設定をするとパケットが全てDefualt Gatewayに流れてしまい接続ができなくなるので、手動でルーティングから削除します。OpenWrtのリポジトリからGretapのパッケージをインストールして/etc/config/networkの設定をします。

packages

gre - 1-11
kmod-gre - 4.14.195-1
kmod-gre6 - 4.14.195-1
kmod-br-netfilter - 4.14.195-1

WireGuard (interface)

Firewall

General SettingsのInputを有効にしないとなぜか繋がりません。

/etc/config/network

'''

config interface 'lan'
	option type 'bridge'
	option proto 'static'
	option ipaddr '192.168.1.17'
	option netmask '255.255.255.192'
	option ip6assign '60'
	option gateway '192.168.1.1'
	list dns '8.8.8.8'
	list dns '1.1.1.1'
	option macaddr 'xx:xx:xx:xx:xx:xx'
	option ifname 'eth0.1 gre4t-gt'


...

config interface 'mesh'
	option proto 'static'
	option netmask '255.255.255.0'
	option ipaddr '10.101.0.17'

config interface 'wg'
	option proto 'wireguard'
	option private_key 'xxxxxxxxxxxxxxxx'
	option listen_port '8889'
	list addresses '192.168.2.17/26'

config wireguard_wg
	option public_key 'xxxxxxxxxxxxxxxx'
	option persistent_keepalive '25'
	option endpoint_port '8888'
	option endpoint_host '10.101.0.14'
	list allowed_ips '192.168.2.0/26'
	list allowed_ips '10.101.0.0/24'
	list allowed_ips '192.168.1.0/26'

config interface 'gt'
    option type 'bridge'
	option proto 'gretap'
	option ipaddr '192.168.2.17'
	option peeraddr '192.168.2.14'
	#option force_link '1'
	#option mtu '1500'
    option delegate '0'

ルーティングの修正

ip r del 10.101.0.14 via 192.168.1.1
ip r del 192.168.2.14 via 192.168.1.1

追記

firewallの追加です。

/etc/firewall.user

iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu;

routingの問題はOpenWrt仕様の特有の問題なので、それを回避するためにInterfacesの設定ではDefault GWの設定はしません。その代わりにあまり良い方法とは言えませんがrc.localで設定します。

/etc/rc.local

sleep 20
ip route add default via 192.168.1.1 dev br-lan

exit 0

追記1.1

OpenWrtのソースを眺めていたら、隠し設定があるらしいことに気がつきました。検索して調べてみると公式HPでも記述がありました。Wireguardをデフォルトルート以外で使うときはこの設定(option nohostroute '1')を使えば良さそうです。

  • https://openwrt.org/docs/guide-user/network/tunneling_interface_protocols

/etc/config/network (例)

onfig interface 'wg'
	option proto 'wireguard'
	option private_key 'xxxxxxxxxxxxxxxx'
	option listen_port '8001'
	option nohostroute '1'
	list addresses '192.168.2.6/26'

config wireguard_wg
	option endpoint_port '8000'
	option public_key 'xxxxxxxxxxxxxxxx'
	option endpoint_host '10.200.0.100'
	option persistent_keepalive '25'
	option nohostroute '1'
	list allowed_ips '192.168.1.0/26'
	list allowed_ips '192.168.2.0/26'

config interface 'gt'
	option type 'bridge'
	option proto 'gretap'
	option ipaddr '192.168.2.6'
	option peeraddr '192.168.2.5'
	option nohostroute '1'
	option delegate '0'

追記2

Firewallルールを少し変えてみました。

General settingsのInputをrejectにした場合、greプロトコルを通すためにiptablesのルールを追加します。

/etc/firewall.user

iptables -I INPUT -p gre -j ACCEPT
iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu;

さらにOpenWrtのパッケージをインストールします。

opkg install kmod-ipt-nat-extra

参考

  • https://notes.superlogical.ch/pages/note_wg/nolayer2/
  • https://openwrt.org/docs/guide-user/network/tunneling_interface_protocols
  • https://forum.openwrt.org/t/setup-fastest-pseudowire-protocol/36219/11
  • https://forum.openwrt.org/t/solved-gretap-tunnel-with-vlan-802-1q-tagging/20742/2
  • https://backreference.org/2013/07/23/gre-bridging-ipsec-and-nfqueue/
  • https://developers.redhat.com/blog/2019/05/17/an-introduction-to-linux-virtual-interfaces-tunnels/
  • https://medium.com/@david.waiting/a-beginners-guide-to-generic-routing-encapsulation-fb2b4fb63abb
  • https://forum.archive.openwrt.org/viewtopic.php?id=59150