広告 デバイス

【トラブル事例】VPS+VPN(WireGuard)で接続できない時の解決方法

※本ページには、プロモーション(広告)が含まれています。

VPS+VPN(WireGuard)の構成
悩んでいる人
悩んでいる人

VPSとWireGuardを使ってVPN環境を構築した。

ただ、環境によって接続できる場合と接続できない場合があるため、原因と解決策を教えて欲しい。

こんなお悩みを解決します。

これまでに、WireGuardでVPN接続する方法を解説してきました。

一方、諸事情で自宅のプロバイダーを変更したところ、これまで利用できていたWireGuardによるVPN接続が利用できなくなりました。

実は、インフラ周りの変更に伴い、MTU(Maximum Transmission Unit)やMSS(Maximum Segment Size)の設定に影響が出ていたんですよね。

この記事では、複数の拠点にVPN接続している状況下において、特定の拠点間のみ通信できない場合の改善方法について解説します。

記事を読み終えると、「WireGuardでVPN接続できない」といったトラブル事例とその解決策について知ることができますよ!

前提条件

環境構築の方法は、下記の記事を参考にしてください。

あわせて読みたい
【解説】VPS+VPN(WireGuard)による自宅サーバの公開方法を分かりやすく解説!(VPS契約編)

続きを見る

あわせて読みたい
【解説】VPS+VPN(WireGuard)による自宅サーバの公開方法(VPN設定編)

続きを見る

あわせて読みたい
【解説】VPS+VPN(WireGuard)による自宅サーバの公開方法(ルーティング設定編)

続きを見る

あわせて読みたい
【番外編】VPS+VPN(WireGuard)による自宅サーバの公開方法(iptablesのサンプルconfig)

続きを見る

ネットワーク構成

以前の記事を参考に、今回は以下のような構成を考えます。

WireGuardはDockerコンテナで起動しているものとします。

VPS+VPN(WireGuard)の構成

スマホ、VPS、別宅ネットワーク、自宅ネットワークの構成はそれぞれ以下のようになります。

対象割り当てられるIP備考
スマホ(VPN Client Phone)【WireGuard】10.1.2.4-
VPS(VPN Server)【WireGuard】10.1.2.1WireGuardで用いるポートは解放済み。
別宅ネットワーク:別宅サーバ2(VPN Client Other)【WireGuard】10.1.2.2
【WireGuardが動作するDocker】10.0.10.2
【LAN】192.168.0.2
Dockerネットワーク(10.0.10.0/24)はLAN(192.168.0.0/24)と通信できる状態とする。
別宅ネットワーク:別宅サーバ3【LAN】192.168.0.3WireGuardやDockerのネットワークにはアクセスできない。
自宅ネットワーク:自宅サーバ2(VPN Client Home)【WireGuard】10.1.2.3
【WireGuardが動作するDocker】10.0.20.2
【LAN】192.168.11.2
Dockerネットワーク(10.0.20.0/24)はLAN(192.168.11.0/24)と通信できる状態とする。
自宅ネットワーク:自宅サーバ3【LAN】192.168.11.3WireGuardやDockerのネットワークにはアクセスできない。
それぞれのネットワークの状態

上記のネットワークにおいて、別宅ネットワーク内にあるサーバにアクセスした場合の経路は以下のようになります。

別宅ネットワーク内のサーバへのアクセス過程

また、自宅ネットワーク内にあるサーバにアクセスした場合の経路は、以下のようになります。

自宅ネットワーク内のサーバへのアクセス過程

VPSにおける設定

VPSにおける設定内容を以下に示します。

ちなみに、ベースは以下のリンクにあるものを利用しています。

https://github.com/yuruto-free/vpnaccess-wireguard-nginx

ディレクトリ構成


./
|-- docker-compose.yml
|-- envs/
|   `-- wireguard/
|       `-- .env
|-- wireguard
|   |-- templates/
|   |   |-- server.conf
|   |   `-- peer.conf
|   `-- iptables_script/
|       |-- postup.sh
|       |-- postdown.sh
|       |-- conf.up.d/
|       |   |-- 01-routing-other-network.conf
|       |   `-- 02-routing-home-network.conf
|       `-- conf.down.d/
|           |-- 01-routing-other-network.conf
|           `-- 02-routing-home-network.conf
`-- wrapper.sh

envs/wireguard/.env

環境変数は例として示すため、実際に理解する際は自身の環境に読み替えて設定してください。

SERVERURL=example.vpn.com
SERVERPORT=51820
PEERS=OtherNetwork,HomeNetwork,myPhone
PEERDNS=8.8.8.8,10.1.2.1
INTERNAL_SUBNET=10.1.2.0/24
MTU=1380
KEEP_ALIVE=25
ALLOWEDIPS=10.1.2.0/24
SERVER_ALLOWEDIPS_PEER_OtherNetwork=10.0.10.0/24
SERVER_ALLOWEDIPS_PEER_HomeNetwork=10.0.20.0/24

docker-compose.yml

version: '3.7'

x-logging:
    &json-logging
    driver: json-file
    options:
        max-size: "1m"
        max-file: "3"

services:
  wireguard:
    image: lscr.io/linuxserver/wireguard:latest
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      - PUID=1000 # VPS上で「id -u ${USER}」を実行し、その出力結果を反映
      - PGID=1000 # VPS上で「id -g ${USER}」を実行し、その出力結果を反映
      - TZ=Asia/Tokyo
    env_file:
      - ./envs/wireguard/.env
    networks:
      - vpn
    ports:
      - 51820:51820/udp
    volumes:
      - /lib/modules:/lib/modules
      - ./wireguard:/config
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    restart: always
    logging: *json-logging

networks:
  vpn:
    name: vpn

templates/server.conf・peer.conf

templates/server.confは以下のようになります。

[Interface]
Address = ${INTERFACE}.1
ListenPort = 51820
MTU = ${MTU:-1420}
PrivateKey = $(cat /config/server/privatekey-server)
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth+ -j MASQUERADE; iptables -A FORWARD -i %i -o %i -j ACCEPT
PostUp = /config/iptables_script/postup.sh
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth+ -j MASQUERADE; iptables -D FORWARD -i %i -o %i -j ACCEPT
PostDown = /config/iptables_script/postdown.sh

また、templates/peer.confは以下のようになります。

[Interface]
Address = ${CLIENT_IP}
PrivateKey = $(cat /config/${PEER_ID}/privatekey-${PEER_ID})
ListenPort = 51820
MTU = ${MTU:-1420}
DNS = ${PEERDNS}

[Peer]
PublicKey = $(cat /config/server/publickey-server)
PresharedKey = $(cat /config/${PEER_ID}/presharedkey-${PEER_ID})
Endpoint = ${SERVERURL}:${SERVERPORT}
AllowedIPs = ${ALLOWEDIPS}
PersistentKeepAlive = ${KEEP_ALIVE:-25}

postup.sh・postdown.sh

postup.shはWireGuardのコンテナ起動時に呼び出されるスクリプトで、conf.up.d以下にあるconfファイルに記載されたコマンドを実行するスクリプトになります。

#!/bin/bash

readonly base_dir=$(cd $(dirname $0) && pwd)

ls ${base_dir}/conf.up.d/*.conf | while read config_file; do
    echo "[#] - ${config_file}"
    cat ${config_file} | grep -v "^\W*$\|\s*#.*" | while read cmd; do
        echo "[#]   ${cmd}"
        eval "${cmd}"
    done
done

似たような位置づけのスクリプトとしてpostdown.shがあり、WireGuardのコンテナ終了時に呼び出されます。

このスクリプトは、conf.down.d以下にあるconfファイルに記載されたコマンドを実行するスクリプトになります。

#!/bin/bash

readonly base_dir=$(cd $(dirname $0) && pwd)

ls ${base_dir}/conf.down.d/*.conf | while read config_file; do
    echo "[#] - ${config_file}"
    cat ${config_file} | grep -v "^\W*$\|\s*#.*" | while read cmd; do
        echo "[#]   ${cmd}"
        eval "${cmd}"
    done
done

iptables

以下の2つは最も重要なiptablesの設定ファイルとなります。

まずは、別宅ネットワーク(OtherNetwork)向けの設定です。

# conf.up.d/01-routing-other-network.conf
# For Web Server
iptables -t nat -A PREROUTING -p tcp -d 192.168.0.3/32 --dport 80 -j DNAT --to-destination 10.0.10.2:80
# IP masquerade
iptables -t nat -A POSTROUTING -d 10.0.10.0/24 -j MASQUERADE
# conf.down.d/01-routing-other-network.conf
# For Web Server
iptables -t nat -D PREROUTING -p tcp -d 192.168.0.3/32 --dport 80 -j DNAT --to-destination 10.0.10.2:80
# IP masquerade
iptables -t nat -D POSTROUTING -d 10.0.10.0/24 -j MASQUERADE

続いて、自宅ネットワーク(HomeNetwork)向けの設定です。

# conf.up.d/02-routing-home-network.conf
# For Web Server
iptables -t nat -A PREROUTING -p tcp -d 192.168.11.3/32 --dport 80 -j DNAT --to-destination 10.0.20.2:80
# IP masquerade
iptables -t nat -A POSTROUTING -d 10.0.20.0/24 -j MASQUERADE
# conf.down.d/02-routing-home-network.conf
# For Web Server
iptables -t nat -D PREROUTING -p tcp -d 192.168.11.3/32 --dport 80 -j DNAT --to-destination 10.0.20.2:80
# IP masquerade
iptables -t nat -D POSTROUTING -d 10.0.20.0/24 -j MASQUERADE

自宅・別宅における設定

docker-compose.ymlで割り当てるIPアドレスが異なるだけであるため、自宅ネットワークを対象に設定情報を示します。

また、以降の設定は下記のリンクにあるものをベースに構築しています。

https://github.com/yuruto-free/wireguard-local-access-client

ディレクトリ構成


./
|-- docker-compose.yml
|-- config
|   |-- wg0.conf
|   `-- iptables_script/
|       |-- postup.sh
|       |-- postdown.sh
|       |-- conf.up.d/
|       |   `-- 02-routing-home-network.conf
|       `-- conf.down.d/
|           `-- 02-routing-home-network.conf
`-- wrapper.sh

docker-compose.yml

version: '3.7'

x-logging:
  &json-logging
  driver: json-file
  options:
    max-size: "1m"
    max-file: "3"

services:
  wireguard:
    image: lscr.io/linuxserver/wireguard:latest
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      - PUID=1000 # 自宅サーバ上で「id -u ${USER}」を実行し、その出力結果を反映
      - PGID=1000 # 自宅サーバ上で「id -g ${USER}」を実行し、その出力結果を反映
      - TZ=Asia/Tokyo
    networks:
      backbone:
        ipv4_address: 10.0.20.2
    volumes:
      - /lib/modules:/lib/modules
      - ./config:/config
    restart: always
    logging: *json-logging
    extra_hosts:
      # LANで構成されるネットワーク(192.168.11.0/24)とDockerネットワーク(10.0.20.0/24)を共存させる
      - "host.docker.internal:10.0.20.1"

networks:
  backbone:
    name: backbone
    driver: bridge
    driver_opts:
      com.docker.network.driver.mtu: 1480 # 必要に応じて設定すること
    ipam:
      driver: default
      config:
        - subnet: 10.0.20.0/24

postup.shpostdown.shはVPS側と同じ内容のため、省略します。

wg0.conf

VPS上で生成したconfigpeer_OtherNetwork/peer_OtherNetwork.confpeer_HomeNetwork/peer_HomeNetwork.conf)をコピーし、PostUpとPostDownの記載を追記します。

[Interface]
Address = 10.1.2.3
PrivateKey = abcdefghijklmnOPQRSTUvwxyz0123456789!*+/?>=<
ListenPort = 51820
MTU = 1380
DNS = 8.8.8.8,10.1.2.1
PostUp = /config/iptables_script/postup.sh     # 追加
PostDown = /config/iptables_script/postdown.sh # 追加

[Peer]
PublicKey = 0123456789ABCDEFGHijklmnopqrstuVWXYZ!*+/?>=<
PresharedKey = 0123456789!*+/?>=<0123456789abcdefghijklmnopqrstuvwxyz
Endpoint = example.vpn.com:51820
AllowedIPs = 10.1.2.0/24
PersistentKeepAlive = 25

iptables

以下は最も重要なiptablesの設定ファイルとなります。

conf.up.d/02-routing-home-network.confの設定内容は以下のようになります。

# conf.up.d/02-routing-home-network.conf
# For Web Server
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.11.3:80
# IP masquerade
iptables -t nat -A POSTROUTING -d 192.168.11.0/24 -j MASQUERADE

また、conf.down.d/02-routing-home-network.confの設定内容は以下のようになります。

# conf.down.d/02-routing-home-network.conf
# For Web Server
iptables -t nat -D PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.11.3:80
# IP masquerade
iptables -t nat -D POSTROUTING -d 192.168.11.0/24 -j MASQUERADE

トラブルの内容

今回発生したトラブルを解説します。

VPN接続中に通信できる例

別宅ネットワーク内にある別宅サーバ3にアクセスする時の通信経路は、以下のようになります。

このケースでは、問題なく接続できています。

VPN接続時の成功例

以降で詳細の通信ログを紹介します。

VPS上の通信ログ

リクエスト(HTTP: GET / HTTP/1.1)を出した後、レスポンス(HTTP: HTTP/1.1 200 OK)が返ってきていることが分かります。

tcpdump -ttttt -n -i any tcp and \( net 10.1.2.0/24 or net 10.0.10.0/24 or net 192.168.0.0/24 \) and ! port 22
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
 00:00:00.000000 wg0   In  IP 10.1.2.4.43952 > 192.168.0.3.80: Flags [S],  seq 2413258095, win 65535, options [mss 1340,sackOK,TS val 1027120945 ecr 0,nop,wscale 9], length 0
 00:00:00.000030 wg0   Out IP 10.1.2.1.43952 > 10.0.10.2.80:   Flags [S],  seq 2413258095, win 65535, options [mss 1340,sackOK,TS val 1027120945 ecr 0,nop,wscale 9], length 0
 00:00:00.012366 wg0   In  IP 10.0.10.2.80   > 10.1.2.1.43952: Flags [S.], seq 1806506038, ack 2413258096, win 65160, options [mss 1460,sackOK,TS val 2637933584 ecr 1027120945,nop,wscale 7], length 0
 00:00:00.012381 wg0   Out IP 192.168.0.3.80 > 10.1.2.4.43952: Flags [S.], seq 1806506038, ack 2413258096, win 65160, options [mss 1460,sackOK,TS val 2637933584 ecr 1027120945,nop,wscale 7], length 0
 00:00:00.027284 wg0   In  IP 10.1.2.4.43952 > 192.168.0.3.80: Flags [.],  ack 1, win 128, options [nop,nop,TS val 1027120985 ecr 2637933584], length 0
 00:00:00.027298 wg0   Out IP 10.1.2.1.43952 > 10.0.10.2.80:   Flags [.],  ack 1, win 128, options [nop,nop,TS val 1027120985 ecr 2637933584], length 0
 00:00:00.035072 wg0   In  IP 10.1.2.4.43952 > 192.168.0.3.80: Flags [P.], seq 1:435, ack 1, win 128, options [nop,nop,TS val 1027120993 ecr 2637933584], length 434: HTTP: GET / HTTP/1.1
 00:00:00.035084 wg0   Out IP 10.1.2.1.43952 > 10.0.10.2.80:   Flags [P.], seq 1:435, ack 1, win 128, options [nop,nop,TS val 1027120993 ecr 2637933584], length 434
 00:00:00.047448 wg0   In  IP 10.0.10.2.80   > 10.1.2.1.43952: Flags [.],  ack 435, win 506, options [nop,nop,TS val 2637933618 ecr 1027120993], length 0
 00:00:00.047460 wg0   Out IP 192.168.0.3.80 > 10.1.2.4.43952: Flags [.],  ack 435, win 506, options [nop,nop,TS val 2637933618 ecr 1027120993], length 0
 00:00:00.048478 wg0   In  IP 10.0.10.2.80   > 10.1.2.1.43952: Flags [.],  seq 1:1329, ack 435, win 506, options [nop,nop,TS val 2637933619 ecr 1027120993], length 1328
 00:00:00.048487 wg0   Out IP 192.168.0.3.80 > 10.1.2.4.43952: Flags [.],  seq 1:1329, ack 435, win 506, options [nop,nop,TS val 2637933619 ecr 1027120993], length 1328: HTTP: HTTP/1.1 200 OK
 00:00:00.048576 wg0   In  IP 10.0.10.2.80   > 10.1.2.1.43952: Flags [P.], seq 1329:1349, ack 435, win 506, options [nop,nop,TS val 2637933619 ecr 1027120993], length 20
 00:00:00.048589 wg0   Out IP 192.168.0.3.80 > 10.1.2.4.43952: Flags [P.], seq 1329:1349, ack 435, win 506, options [nop,nop,TS val 2637933619 ecr 1027120993], length 20: HTTP
 00:00:00.062908 wg0   In  IP 10.1.2.4.43952 > 192.168.0.3.80: Flags [.],  ack 1, win 131, options [nop,nop,TS val 1027121021 ecr 2637933618,nop,nop,sack 1 {1329:1349}], length 0
 00:00:00.062920 wg0   Out IP 10.1.2.1.43952 > 10.0.10.2.80:   Flags [.],  ack 1, win 131, options [nop,nop,TS val 1027121021 ecr 2637933618,nop,nop,sack 1 {1329:1349}], length 0
(以下略)

別宅サーバ2の通信ログ

別宅サーバ3に渡したリクエスト(HTTP: GET / HTTP/1.1)に対して、別宅サーバ3からのレスポンス(HTTP: HTTP/1.1 200 OK)をVPS側に返せていることが確認できます。

tcpdump -ttttt -n -i any tcp and \( net 10.1.2.0/24 or net 10.0.10.0/24 or net 192.168.0.0/24 \) and ! port 22
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
 00:00:00.000000 wg0   In  IP 10.1.2.1.43952  > 10.0.10.2.80:    Flags [S],  seq 2413258095, win 65535, options [mss 1340,sackOK,TS val 1027120945 ecr 0,nop,wscale 9], length 0
 00:00:00.000104 eth0  Out IP 10.0.10.2.43952 > 192.168.0.3.80:  Flags [S],  seq 2413258095, win 65535, options [mss 1340,sackOK,TS val 1027120945 ecr 0,nop,wscale 9], length 0
 00:00:00.000304 eth0  In  IP 192.168.0.3.80  > 10.0.10.2.43952: Flags [S.], seq 1806506038, ack 2413258096, win 65160, options [mss 1460,sackOK,TS val 2637933584 ecr 1027120945,nop,wscale 7], length 0
 00:00:00.000341 wg0   Out IP 10.0.10.2.80    > 10.1.2.1.43952:  Flags [S.], seq 1806506038, ack 2413258096, win 65160, options [mss 1460,sackOK,TS val 2637933584 ecr 1027120945,nop,wscale 7], length 0
 00:00:00.027074 wg0   In  IP 10.1.2.1.43952  > 10.0.10.2.80:    Flags [.],  ack 1, win 128, options [nop,nop,TS val 1027120985 ecr 2637933584], length 0
 00:00:00.027115 eth0  Out IP 10.0.10.2.43952 > 192.168.0.3.80:  Flags [.],  ack 1, win 128, options [nop,nop,TS val 1027120985 ecr 2637933584], length 0
 00:00:00.034938 wg0   In  IP 10.1.2.1.43952  > 10.0.10.2.80:    Flags [P.], seq 1:435, ack 1, win 128, options [nop,nop,TS val 1027120993 ecr 2637933584], length 434
 00:00:00.034975 eth0  Out IP 10.0.10.2.43952 > 192.168.0.3.80:  Flags [P.], seq 1:435, ack 1, win 128, options [nop,nop,TS val 1027120993 ecr 2637933584], length 434: HTTP: GET / HTTP/1.1
 00:00:00.035094 eth0  In  IP 192.168.0.3.80  > 10.0.10.2.43952: Flags [.],  ack 435, win 506, options [nop,nop,TS val 2637933618 ecr 1027120993], length 0
 00:00:00.035128 wg0   Out IP 10.0.10.2.80    > 10.1.2.1.43952:  Flags [.],  ack 435, win 506, options [nop,nop,TS val 2637933618 ecr 1027120993], length 0
 00:00:00.036173 eth0  In  IP 192.168.0.3.80  > 10.0.10.2.43952: Flags [P.], seq 1:1349, ack 435, win 506, options [nop,nop,TS val 2637933619 ecr 1027120993], length 1348: HTTP: HTTP/1.1 200 OK
 00:00:00.036219 wg0   Out IP 10.0.10.2.80    > 10.1.2.1.43952:  Flags [P.], seq 1:1349, ack 435, win 506, options [nop,nop,TS val 2637933619 ecr 1027120993], length 1348
 00:00:00.062725 wg0   In  IP 10.1.2.1.43952  > 10.0.10.2.80:    Flags [.],  ack 1, win 131, options [nop,nop,TS val 1027121021 ecr 2637933618,nop,nop,sack 1 {1329:1349}], length 0
 00:00:00.062769 eth0  Out IP 10.0.10.2.43952 > 192.168.0.3.80:  Flags [.],  ack 1, win 131, options [nop,nop,TS val 1027121021 ecr 2637933618,nop,nop,sack 1 {1329:1349}], length 0
(以下略)

VPN接続中に通信できない例

一方、自宅ネットワーク内にある自宅サーバ3にアクセスする時の通信経路は、以下のようになります。

この時、自宅サーバ2からVPSに向けた通信が届いていませんでした。

VPN接続時の失敗例

詳細な通信ログは以下のようになります。

VPS上の通信ログ

リクエスト(HTTP: GET / HTTP/1.1)を出した後、0.1秒経ってもレスポンスが返ってこないことが分かります。

tcpdump -ttttt -n -i any tcp and \( net 10.1.2.0/24 or net 10.0.20.0/24 or net 192.168.11.0/24 \) and ! port 22
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
 00:00:00.000000 wg0   In  IP 10.1.2.4.44486  > 192.168.11.3.80: Flags [S],  seq 2282162397, win 65535, options [mss 1340,sackOK,TS val 1026978371 ecr 0,nop,wscale 9], length 0
 00:00:00.000025 wg0   Out IP 10.1.2.1.44486  > 10.0.20.2.80:    Flags [S],  seq 2282162397, win 65535, options [mss 1340,sackOK,TS val 1026978371 ecr 0,nop,wscale 9], length 0
 00:00:00.014145 wg0   In  IP 10.0.20.2.80    > 10.1.2.1.44486:  Flags [S.], seq 1716633062, ack 2282162398, win 65160, options [mss 1460,sackOK,TS val 3510018023 ecr 1026978371,nop,wscale 7], length 0
 00:00:00.014169 wg0   Out IP 192.168.11.3.80 > 10.1.2.4.44486:  Flags [S.], seq 1716633062, ack 2282162398, win 65160, options [mss 1460,sackOK,TS val 3510018023 ecr 1026978371,nop,wscale 7], length 0
 00:00:00.028542 wg0   In  IP 10.1.2.4.44486  > 192.168.11.3.80: Flags [.],  ack 1, win 128, options [nop,nop,TS val 1026978400 ecr 3510018023], length 0
 00:00:00.028558 wg0   Out IP 10.1.2.1.44486  > 10.0.20.2.80:    Flags [.],  ack 1, win 128, options [nop,nop,TS val 1026978400 ecr 3510018023], length 0
 00:00:00.028571 wg0   In  IP 10.1.2.4.44486  > 192.168.11.3.80: Flags [P.], seq 1:431, ack 1, win 128, options [nop,nop,TS val 1026978400 ecr 3510018023], length 430: HTTP: GET / HTTP/1.1
 00:00:00.028576 wg0   Out IP 10.1.2.1.44486  > 10.0.20.2.80:    Flags [P.], seq 1:431, ack 1, win 128, options [nop,nop,TS val 1026978400 ecr 3510018023], length 430: HTTP: GET / HTTP/1.1
 00:00:00.043273 wg0   In  IP 10.0.20.2.80    > 10.1.2.1.44486:  Flags [.],  ack 431, win 506, options [nop,nop,TS val 3510018052 ecr 1026978400], length 0
 00:00:00.043285 wg0   Out IP 192.168.11.3.80 > 10.1.2.4.44486:  Flags [.],  ack 431, win 506, options [nop,nop,TS val 3510018052 ecr 1026978400], length 0
 00:00:00.102801 wg0   In  IP 10.0.20.2.80    > 10.1.2.1.44486:  Flags [P.], seq 7969:8269, ack 431, win 506, options [nop,nop,TS val 3510018109 ecr 1026978400], length 300: HTTP
 00:00:00.102815 wg0   Out IP 192.168.11.3.80 > 10.1.2.4.44486:  Flags [P.], seq 7969:8269, ack 431, win 506, options [nop,nop,TS val 3510018109 ecr 1026978400], length 300: HTTP
 00:00:00.117046 wg0   In  IP 10.1.2.4.44486  > 192.168.11.3.80: Flags [.],  ack 1, win 131, options [nop,nop,TS val 1026978488 ecr 3510018052,nop,nop,sack 1 {7969:8269}], length 0
 00:00:00.117059 wg0   Out IP 10.1.2.1.44486  > 10.0.20.2.80:    Flags [.],  ack 1, win 131, options [nop,nop,TS val 1026978488 ecr 3510018052,nop,nop,sack 1 {7969:8269}], length 0
 (以下略)

自宅サーバ2上の通信ログ

リクエスト(HTTP: GET / HTTP/1.1)を出した後、レスポンス(HTTP: HTTP/1.1 200 OK)を何度も返していることが分かります。

ここから、自宅サーバ2からVPSにレスポンスが返せていないと考えられます。

tcpdump -ttttt -n -i any tcp and \( net 10.1.2.0/24 or net 10.0.20.0/24 or net 192.168.11.0/24 \) and ! port 22
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
 00:00:00.000000 wg0   In  IP 10.1.2.1.44486  > 10.0.20.2.80:    Flags [S],  seq 2282162397, win 65535, options [mss 1340,sackOK,TS val 1026978371 ecr 0,nop,wscale 9], length 0
 00:00:00.000084 eth0  Out IP 10.0.20.2.44486 > 192.168.11.3.80: Flags [S],  seq 2282162397, win 65535, options [mss 1340,sackOK,TS val 1026978371 ecr 0,nop,wscale 9], length 0
 00:00:00.001005 eth0  In  IP 192.168.11.3.80 > 10.0.20.2.44486: Flags [S.], seq 1716633062, ack 2282162398, win 65160, options [mss 1460,sackOK,TS val 3510018023 ecr 1026978371,nop,wscale 7], length 0
 00:00:00.001040 wg0   Out IP 10.0.20.2.80    > 10.1.2.1.44486:  Flags [S.], seq 1716633062, ack 2282162398, win 65160, options [mss 1460,sackOK,TS val 3510018023 ecr 1026978371,nop,wscale 7], length 0
 00:00:00.028635 wg0   In  IP 10.1.2.1.44486  > 10.0.20.2.80:    Flags [.],  ack 1, win 128, options [nop,nop,TS val 1026978400 ecr 3510018023], length 0
 00:00:00.028642 wg0   In  IP 10.1.2.1.44486  > 10.0.20.2.80:    Flags [P.], seq 1:431, ack 1, win 128, options [nop,nop,TS val 1026978400 ecr 3510018023], length 430: HTTP: GET / HTTP/1.1
 00:00:00.028695 eth0  Out IP 10.0.20.2.44486 > 192.168.11.3.80: Flags [.],  ack 1, win 128, options [nop,nop,TS val 1026978400 ecr 3510018023], length 0
 00:00:00.028714 eth0  Out IP 10.0.20.2.44486 > 192.168.11.3.80: Flags [P.], seq 1:431, ack 1, win 128, options [nop,nop,TS val 1026978400 ecr 3510018023], length 430: HTTP: GET / HTTP/1.1
 00:00:00.029642 eth0  In  IP 192.168.11.3.80 > 10.0.20.2.44486: Flags [.],  ack 431, win 506, options [nop,nop,TS val 3510018052 ecr 1026978400], length 0
 00:00:00.029676 wg0   Out IP 10.0.20.2.80    > 10.1.2.1.44486:  Flags [.],  ack 431, win 506, options [nop,nop,TS val 3510018052 ecr 1026978400], length 0
 00:00:00.088407 eth0  In  IP 192.168.11.3.80 > 10.0.20.2.44486: Flags [P.], seq 1:2657, ack 431, win 506, options [nop,nop,TS val 3510018109 ecr 1026978400], length 2656: HTTP: HTTP/1.1 200 OK
 00:00:00.088450 wg0   Out IP 10.0.20.2.80    > 10.1.2.1.44486:  Flags [P.], seq 1:2657, ack 431, win 506, options [nop,nop,TS val 3510018109 ecr 1026978400], length 2656: HTTP: HTTP/1.1 200 OK
 00:00:00.088505 eth0  In  IP 192.168.11.3.80 > 10.0.20.2.44486: Flags [P.], seq 2657:5313, ack 431, win 506, options [nop,nop,TS val 3510018109 ecr 1026978400], length 2656: HTTP
 00:00:00.088536 wg0   Out IP 10.0.20.2.80    > 10.1.2.1.44486:  Flags [P.], seq 2657:5313, ack 431, win 506, options [nop,nop,TS val 3510018109 ecr 1026978400], length 2656: HTTP
 00:00:00.088575 eth0  In  IP 192.168.11.3.80 > 10.0.20.2.44486: Flags [P.], seq 5313:7969, ack 431, win 506, options [nop,nop,TS val 3510018109 ecr 1026978400], length 2656: HTTP
 00:00:00.088605 wg0   Out IP 10.0.20.2.80    > 10.1.2.1.44486:  Flags [P.], seq 5313:7969, ack 431, win 506, options [nop,nop,TS val 3510018109 ecr 1026978400], length 2656: HTTP
 00:00:00.088636 eth0  In  IP 192.168.11.3.80 > 10.0.20.2.44486: Flags [P.], seq 7969:8269, ack 431, win 506, options [nop,nop,TS val 3510018109 ecr 1026978400], length 300: HTTP
 00:00:00.088663 wg0   Out IP 10.0.20.2.80    > 10.1.2.1.44486:  Flags [P.], seq 7969:8269, ack 431, win 506, options [nop,nop,TS val 3510018109 ecr 1026978400], length 300: HTTP
 00:00:00.088681 eth0  In  IP 192.168.11.3.80 > 10.0.20.2.44486: Flags [P.], seq 8269:10925, ack 431, win 506, options [nop,nop,TS val 3510018109 ecr 1026978400], length 2656: HTTP
 00:00:00.088710 wg0   Out IP 10.0.20.2.80    > 10.1.2.1.44486:  Flags [P.], seq 8269:10925, ack 431, win 506, options [nop,nop,TS val 3510018109 ecr 1026978400], length 2656: HTTP
 00:00:00.088739 eth0  In  IP 192.168.11.3.80 > 10.0.20.2.44486: Flags [.],  seq 10925:12253, ack 431, win 506, options [nop,nop,TS val 3510018109 ecr 1026978400], length 1328: HTTP
 00:00:00.088766 wg0   Out IP 10.0.20.2.80    > 10.1.2.1.44486:  Flags [.],  seq 10925:12253, ack 431, win 506, options [nop,nop,TS val 3510018109 ecr 1026978400], length 1328: HTTP
 00:00:00.116795 wg0   In  IP 10.1.2.1.44486  > 10.0.20.2.80:    Flags [.],  ack 1, win 131, options [nop,nop,TS val 1026978488 ecr 3510018052,nop,nop,sack 1 {7969:8269}], length 0
 00:00:00.116823 eth0  Out IP 10.0.20.2.44486 > 192.168.11.3.80: Flags [.],  ack 1, win 131, options [nop,nop,TS val 1026978488 ecr 3510018052,nop,nop,sack 1 {7969:8269}], length 0
 00:00:00.117962 eth0  In  IP 192.168.11.3.80 > 10.0.20.2.44486: Flags [.],  seq 12253:13581, ack 431, win 506, options [nop,nop,TS val 3510018140 ecr 1026978488], length 1328: HTTP
 00:00:00.117982 wg0   Out IP 10.0.20.2.80    > 10.1.2.1.44486:  Flags [.],  seq 12253:13581, ack 431, win 506, options [nop,nop,TS val 3510018140 ecr 1026978488], length 1328: HTTP
 00:00:00.151136 eth0  In  IP 192.168.11.3.80 > 10.0.20.2.44486: Flags [.],  seq 1:1329, ack 431, win 506, options [nop,nop,TS val 3510018173 ecr 1026978488], length 1328: HTTP: HTTP/1.1 200 OK
 00:00:00.151163 wg0   Out IP 10.0.20.2.80    > 10.1.2.1.44486:  Flags [.],  seq 1:1329, ack 431, win 506, options [nop,nop,TS val 3510018173 ecr 1026978488], length 1328: HTTP: HTTP/1.1 200 OK
 00:00:00.391056 eth0  In  IP 192.168.11.3.80 > 10.0.20.2.44486: Flags [.],  seq 1:1329, ack 431, win 506, options [nop,nop,TS val 3510018413 ecr 1026978488], length 1328: HTTP: HTTP/1.1 200 OK
 00:00:00.391081 wg0   Out IP 10.0.20.2.80    > 10.1.2.1.44486:  Flags [.],  seq 1:1329, ack 431, win 506, options [nop,nop,TS val 3510018413 ecr 1026978488], length 1328: HTTP: HTTP/1.1 200 OK
 (以下略)

通信ログから分かること

以上を踏まえてリクエスト&レスポンス時に起きていることをまとめると、以下のようになります。

通信ログから分かること3つ

  • VPSから自宅サーバ/別宅サーバに向けた通信(リクエスト)はできる。
  • 別宅サーバからVPSに向けた通信(レスポンス)はできる。
  • 自宅サーバからVPSに向けた通信(レスポンス)はできない。

以降で解説しますが、これらの違いは自宅サーバ/別宅サーバの通信環境が影響しています。

最後に、通信できない原因と解決方法について解説します。

原因と解決方法

最後に、原因と解決方法について解説します。

原因

結論としては、VPS(VPN Server)とサーバ(VPN Client)間のMSS(もしくはMTU)の値が、「スマホとVPS」や「サーバが属するLAN内」と比較して小さいことが原因でした。

MTU(Maximum Transmission Unit)

ネットワークで一回に送信できる最大のデータサイズのこと。

https://atmarkit.itmedia.co.jp/aig/06network/mtu.html

MSS(Maximum Segment Size)

インターネットで標準的に用いられるプロトコル(通信規約)であるTCPで通信する際に指定する、一度にデータを受信できる単位(セグメント)の最大長。

https://e-words.jp/w/%E6%9C%80%E5%A4%A7%E3%82%BB%E3%82%B0%E3%83%A1%E3%83%B3%E3%83%88%E3%82%B5%E3%82%A4%E3%82%BA.html

「MSS = MTU - 40」という関係が成り立ちます。

実際、自宅ネットワーク内のサーバにアクセスした際に起きていた現象を図解すると以下のようになります。

トラブルの要因

LAN内では同じMSS値で通信できるため、わざわざICMPを受信してMSSやフラグメントの処理を見直す仕組みは取り入れていませんでした。

このため、TCP通信に用いるMSS値の更新が行われず通信できない状態となっていました。

解決方法

解決方法としては次の2パターンが考えられますが、フラグメント(≒分割送信)によるスループット低下を避けるため、今回はMSSの設定値を見直す方針としました。

解決方法メリットデメリット
①フラグメントを許可する(DF=Falseとして送信する)アプリケーション側がデータサイズを気にする必要がなくなる。IPパケットがフラグメントされるため、スループットが低下する。
②MSSの設定値を1240にする特定の通信に対するiptablesの設定のみ更新すればよいため、影響範囲を限定できる。最大送信サイズが1280Byte(=1240Byte+40Byte)となるため、大容量通信に時間がかかる。
解決方法一覧

以降では、MSS値の目安の調べ方とiptablesの設定方法について解説します。

MSS値の目安の調べ方

以下のいずれかのパターンに対し、Dockerコンテナ内からpingを送信します。

コマンドを実行するマシンping送信先実行コマンド
VPSサーバ上のDockerコンテナ別宅サーバ上のDockerコンテナ(10.0.10.2)ping -c 1 -M do -w 2 -s <送信データサイズ> 10.0.10.2
VPSサーバ上のDockerコンテナ自宅サーバ上のDockerコンテナ(10.0.20.2)ping -c 1 -M do -w 2 -s <送信データサイズ> 10.0.20.2
別宅サーバ上のDockerコンテナVPSサーバ上のDockerコンテナ(10.1.2.1)ping -c 1 -M do -w 2 -s <送信データサイズ> 10.1.2.1
自宅サーバ上のDockerコンテナVPSサーバ上のDockerコンテナ(10.1.2.1)ping -c 1 -M do -w 2 -s <送信データサイズ> 10.1.2.1
具体的なコマンドの内容

-c 1:1回だけpingを送信する
-M do:フラグメントを禁止する(DF=Trueとする)
-w 2:タイムアウトを2秒に設定する

VPS上で実行した場合の例を以下に示します。

# 別宅サーバ宛のping(10.0.10.2)
ping -c 1 -M do -w 2 -s 1340 10.0.10.2
PING 10.0.10.2 (10.0.10.2) 1340(1368) bytes of data.
1348 bytes from 10.0.10.2: icmp_seq=1 ttl=64 time=12.8 ms

--- 10.0.10.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms # <- パケットが受信できている
# 自宅サーバ宛のping(10.0.20.2)
ping -c 1 -M do -w 2 -s 1340 10.0.20.2
PING 10.0.20.2 (10.0.20.2) 1340(1368) bytes of data.

--- 10.0.20.2 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1004ms # <- パケットロスが発生している

パケットロスが発生した場合は、送信データサイズを少しずつ小さくしていき、送信できるようになるデータサイズを探索します。

# 自宅サーバ宛のping(10.0.20.2)
ping -c 1 -M do -w 2 -s 1340 10.0.20.2 # -> パケットロスが発生
ping -c 1 -M do -w 2 -s 1339 10.0.20.2 # -> パケットロスが発生
ping -c 1 -M do -w 2 -s 1338 10.0.20.2 # -> パケットロスが発生
# (中略)
ping -c 1 -M do -w 2 -s 1242 10.0.20.2 # -> パケットロスが発生
ping -c 1 -M do -w 2 -s 1241 10.0.20.2 # -> パケットロスが発生
ping -c 1 -M do -w 2 -s 1240 10.0.20.2
PING 10.0.20.2 (10.0.20.2) 1240(1268) bytes of data.
1248 bytes from 10.0.20.2: icmp_seq=1 ttl=64 time=14.3 ms

--- 10.0.20.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms # <- パケットが受信できている

iptablesの設定方法

VPS側と自宅サーバでそれぞれ以下のフォーマットを参考に、iptablesを更新します。

対象フォーマット備考
VPSiptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -d 10.0.20.0/24 -j TCPMSS --set-mss <調べたMSS値>サブネットは自身の環境に合わせること
自宅サーバiptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o wg0 -j TCPMSS --set-mss <調べたMSS値>自宅サーバ側は「-o wg0」となる点に注意
iptablesの設定内容

今回の例では、それぞれ以下のように更新すればよいことになりますね。(conf.up.d側のみ記載)

# 【VPS】conf.up.d/02-routing-home-network.conf
# For Web Server
iptables -t nat -A PREROUTING -p tcp -d 192.168.11.3/32 --dport 80 -j DNAT --to-destination 10.0.20.2:80
# IP masquerade
iptables -t nat -A POSTROUTING -d 10.0.20.0/24 -j MASQUERADE
# ==================
# === 下記を追加 ===
# ==================
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -d 10.0.20.0/24 -j TCPMSS --set-mss 1240
# 【自宅サーバ】conf.up.d/02-routing-home-network.conf
# For Web Server
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.11.3:80
# IP masquerade
iptables -t nat -A POSTROUTING -d 192.168.11.0/24 -j MASQUERADE
# ==================
# === 下記を追加 ===
# ==================
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -o wg0 -j TCPMSS --set-mss 1240

まとめ

今回は、MTU値やMSS値の違いにより通信できない原因とその解決策について解説しました。

普段意識することのないパラメータですが、環境の違いに発生しうる現象かつ原因解明がしづらい現象のため、似たようなことで困っている方の助けになれば幸いです。

いずれの場合においても、どこまで上手く動いており、どこでつまづいているかをハッキリさせることが重要になります。

今後もトラブルが発生した段階で解決策をまとめ、記事にしていこうと思います。

素早く環境構築したい方へ

環境構築が比較的容易で、共有サーバよりも、カスタマイズの自由度が高いものを求めている場合、仮想専用サーバ(VPS)を利用することをおすすめします。

詳細は、以下の記事をご覧ください。

あわせて読みたい
【比較】おすすめのVPS 4選

続きを見る

スポンサードリンク

-デバイス
-, ,