Docker-composeでWireguardを立ち上げる

2022年10月12日

VPNまとめを参照されたい。

環境としては、カーネルがWireguardをサポートしているLinuxを使う。つまり、カーネルバージョンが5.6以上であることだ。Rocky 9が5.14なので、これを使ってみる。

docker-compose.yml

docker-compose.ymlの起動方法は、linuxserver / docker-wireguardの下の方にあり、以下である。

version: "2.1"
services:
  wireguard:
    image: lscr.io/linuxserver/wireguard:latest
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/London
      - SERVERURL=wireguard.domain.com #optional
      - SERVERPORT=51820 #optional
      - PEERS=1 #optional
      - PEERDNS=auto #optional
      - INTERNAL_SUBNET=10.13.13.0 #optional
      - ALLOWEDIPS=0.0.0.0/0 #optional
      - LOG_CONFS=true #optional
    volumes:
      - /path/to/appdata/config:/config
      - /lib/modules:/lib/modules
    ports:
      - 51820:51820/udp
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    restart: unless-stopped

これらの意味について調べてみる。解説としては、How to Install Wireguard in Dockerあたり。

NET_ADMIN

このコンテナに様々なネットワーク操作を許すとのこと。具体的に何をするのかわからないが、無ければ困るものらしい。つまり必須。

SYS_MODULE

コンテナにカーネルモジュールのインストールを許すとのこと。ということは、カーネルがサポートしていれば不要なのだろうか。

PUID, PGID

Understanding PUID and PGIDの解説で適当かと思うが、Dockerはコンテナをrootとして動作させてしまうので、そうではない制約された権限で動作させる目的のようだ。

ということは、rootでよければ、このフラグは不要なのだろうか。

TZ

これはAsia/Tokyoに変更する

SERVERURL

サーバのIPアドレスかURLということだが、なぜこれが必要なのか不明。Optionalとなっている。

SERVERPORT

Wireguardの使うポート。デフォルトは51820

PEARS

クライアントの数。単にこの数だけ接続キーが作成されるだけなので、使い回せば1のままで良いかもしれない。

PEERDNS

VPNクライアントが別のDNSを使う場合には、auto以外にしろという。特に変更の必要はない。

INTERNAL_SUBNET

他と競合しなければそのままで良い。

ALLOWEDIPS

What does WireGuard AllowedIPs actually do?WireGuardのAllowed IPsの設定についての補足に説明がある。

しかし、この説明では良くわからない。やりたいことは、以下の三種類になると思う。

  • Wireguardが起動しているサーバとだけトンネル通信ができれば良いのであって、それ以外は現状のままにする。つまり、サーバの中身をいじりたいだけであって、他の通信には影響させたくない。
  • 上とは逆に、すべてのトラフィックをWireguard経由で送受信する。こうすれば、携帯会社などのキャリアにどこと通信しているかを知られることがなくなる。
  • 上のアレンジだが、ローカルにPCの接続しているLAN内にはWireguardを経由しない。それ以外はすべてWiregaurdを経由する。

この三種類の設定を具体的にどうやるのかわからない。

/config

コンフィグファイルの置き場所指定

/lib/modules

カーネルライブラリモジュールの置き場所指定。

net.ipv4.conf.all.src_valid_mark=1

Install Wireguard VPN server with Dockerに説明があるが、正直わからない。ON以外には無いらしい。

起動してみる

不要と思われる部分をコメントアウトしてwireguardを起動してみる。

docker-compose.yml

version: "2.1"
services:
  wireguard:
    image: lscr.io/linuxserver/wireguard:1.0.20210914
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      #- SYS_MODULE
    environment:
      #- PUID=1000
      #- PGID=1000
      - TZ=Asia/Tokyo
      #- SERVERURL=wireguard.domain.com #optional
      #- SERVERPORT=51820 #optional
      - PEERS=1 #optional
      #- PEERDNS=auto #optional
      #- INTERNAL_SUBNET=10.13.13.0 #optional
      #- ALLOWEDIPS=0.0.0.0/0 #optional
      #- LOG_CONFS=true #optional
    volumes:
      - ./config:/config
      #- /lib/modules:/lib/modules
    ports:
      - 51820:51820/udp
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    restart: unless-stopped

以下で起動する。

docker-compose up -d

以下でログを表示

「docker-compose logs -f」

実行結果と評価

Windowsとスマフォから接続してみたが、気がついた点は以下である。

  • config/peer1/peer1.confクライアントコンフィグファイル、あるいはQRコードを使って接続するが、これを使い回すことはできないようだ。つまり、Windowsとスマフォから同時接続するならば、複数のクライアント設定を作成して、それぞれ別のものを使う必要がある。
  • クライアントコンフィグファイルには、当然だが、直接IPアドレスが記述されている。ドメインにするには,SERVERURLを指定する必要がある。
  • 特にWindowsマシンの場合、ローカルなLAN内の他マシンにアクセスできなくなってしまう。なぜなら、いったんネットに出ていって、そこからアクセスしようとするからである。
  • その他の機能は特に問題無いようだ。IP確認などやってみると、サーバのIPになっており、契約プロバイダのIPではない。
  • 予想通り、カーネルモジュールの追加は不要のようで、コンテナ内部の/lib/modulesというディレクトリさえ存在しなかった。

以下のように変更する。

docker-compose.yml

version: "2.1"
services:
  wireguard:
    image: lscr.io/linuxserver/wireguard:1.0.20210914
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      #- SYS_MODULE
    environment:
      #- PUID=1000
      #- PGID=1000
      - TZ=Asia/Tokyo
      - SERVERURL=wireguard.example.com
      #- SERVERPORT=51820 #optional
      - PEERS=10 #optional
      #- PEERDNS=auto #optional
      #- INTERNAL_SUBNET=10.13.13.0 #optional
      - ALLOWEDIPS=0.0.0.0/1, 128.0.0.0/2, 192.0.0.0/9, 192.128.0.0/11, 192.160.0.0/13, 192.169.0.0/16, 192.170.0.0/15, 192.172.0.0/14, 192.176.0.0/12, 192.192.0.0/10, 193.0.0.0/8, 194.0.0.0/7, 196.0.0.0/6, 200.0.0.0/5, 208.0.0.0/4, 224.0.0.0/3
      #- LOG_CONFS=true #optional
    volumes:
      - ./config:/config
      #- /lib/modules:/lib/modules
    ports:
      - 51820:51820/udp
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    restart: unless-stopped

ALLOWEDIPS

SERVERURLとPEERSは説明不要だが、ALLOWEDIPSが問題である。wireguard使用を許可するIPではなく、許可しないIP、つまりwireguardを介さずに生でアクセスするIPを指定したいのに、それはできない。

この問題がHow to exclude local network packets from Wireguard?にあり、最後にWireGuard AllowedIPs Calculatorのリンクがある。

上に示した設定は、ここにAllowed IPsとして「0.0.0.0/0」、Disallowed IPsとして「192.168.0.0/16」を入力した結果だ。実際には、ローカルLANは192.168.3.0/24のみを使用しているのだが、192.168.0.0/16はプライベートアドレスなので、ネットワーク側に出ていってもまるで意味が無いため、まるごと禁止している。

変更の結果

クライアント設定が10個作成され、うち二つをWindows、スマフォで使用した。ローカルなLANの機器にもそのままアクセスが可能になった。クライアントコンフィグファイルには、サーバのIPはアドレスではなく、ドメインが記述されており、IP変更にも耐えられる。