VPNによるNATリフレクションによる外部Webサービスアクセスタイムアウト

VPNによるNATリフレクションによる外部Webサービスアクセスタイムアウト

Strongswan VPNサーバーと複数のサービスを実行しているRaspbian arm64を備えたRaspberry Pi 4Bがあり、外部IP /ドメイン名を介してフローWANにアクセスできます。 LANで同じサービスを使用できるように、ルータでNATリフレクションを使用します。すべてのVPNデバイスからインターネットとLAN上のすべてのデバイスにアクセスできるため、VPNルーティングが正しく機能しているようです。同様に、LANからすべてのVPNデバイスにpingを送信できます。

自分のドメイン名を介して自分のWebサービスにアクセスしようとすると問題が発生します。通常、LAN および WAN からアクセスできるのと同じサービスは、VPN デバイスからアクセスできません。 LAN上の他のデバイスのポートを転送し、ドメイン名を介してVPNデバイスのポートにアクセスしようとすると正常に動作します。したがって、ルーティングとNATの反射は私のネットワーク設定に適しているようです。 VPNと同じサーバー上のドメイン/外部IPを介してWebサイトにアクセスしようとした場合(ローカルIPを介してWebサイトにアクセスしても問題ありません)、期待どおりに機能しません。

私はRaspberry Piのルーティングに問題があると結論付けましたが、どこでデバッグを始めるべきかわかりませんでした。だから、どのプロフィールがここに投稿するのに適しているのかわかりません。この問題を解決するために必要な追加情報をお送りします。

私のStrongswanの設定:

conn ikev2-rsa
    auto=add
    compress=no
    type=tunnel
    keyexchange=ikev2
    fragmentation=yes
    forceencaps=yes

    dpdaction=clear
    dpddelay=300s

    left=%any
    [email protected] (this is set to my real domain name)
    leftcert=strongswan-cert.pem
    leftsendcert=always
    leftsubnet=0.0.0.0/0,::/0

    right=%any
    rightid=%any
    rightauth=pubkey
    rightsourceip=10.2.1.0/24
    rightdns=10.0.0.4
    rightsendcert=never

答え1

私に合った解決策を見つけたので、他の人が同じ問題に遭遇した場合に備えて、ここに投稿する必要があると思いました。

アイデアは、サーバーがパブリックIPを独自のIPとして受け入れ、パケット転送を停止するようにすることです。つまり、VPNに接続していても、ドメイン名を介してサーバーにアクセスできます。

このアプローチの欠点は、パブリックIPアドレスに向けられたすべてのトラフィックがサーバー上で停止されることです。したがって、同じWANアドレスにある複数のデバイスに対してポート転送を設定すると、トラフィックがルータに到達しないため、VPNを介してそのデバイスにアクセスできなくなります。私は特にVPNを使用するときに外部IPアドレスを介してこのサーバー以外のデバイスにほとんどアクセスしないため、この妥協を喜んで受け入れます。ただし、これを認識し、これがあなたの状況にも当てはまるかどうかを確認する必要があります。

これを達成するために、2つの位置パラメータ(パブリックIPアドレスを割り当てたいインターフェイスとドメイン名)を受け入れるbashスクリプトを作成しました。たとえば、使用法は次のとおりです。

sudo ~/externalIP.sh eth0 example.com

このスクリプトは起動時に実行し、IPアドレスが変更された場合は定期的に実行する必要があります。たとえば、root ユーザーの crontab を使用してスクリプトを root で実行することが重要です。

sudo crontab -e

毎時間起動時に実行される例は次のとおりです。

0 * * * * /home/user/externalIP.sh eth0 example.com
@reboot /home/user/externalIP.sh eth0 example.com

最後に、スクリプトのコードは次のようになります。

#!/bin/bash
lookup=($(nslookup $2 | grep -oP '(?<=Address:\s)\d+(.\d+){3}')) # look up my address
if [[ "${#lookup[@]}" -ne "2" ]]; then # exit if the address could not be found
        exit
fi
address="${lookup[1]}/32"
addresses=($(ip addr show dev $1 | grep -oP '\d+(.\d+){3}/32')) # get addresses assigned to my interface
exists=0
for i in "${addresses[@]}"
do
        if [[ "$i" = "$address" ]]; then # check if the address already exists
                exists=1
        elif ! [[ "$i" =~ ^((10)|(192\.168)|(127)|(172\.1[6-9])|(172\.2\d)|(172\.3[0-1]))\. ]]; then # remove superfluous public addresses
                $(ip addr del $i dev $1)
        fi
done
if [[ "$exists" -eq 0 ]]; then # add address if it does not exist yet
        $(ip addr add $address dev $1)
fi

具体的には、コードはパブリックアドレスを見つけ、指定されたインターフェイスに追加します。また、以前に追加されたパブリックアドレスも削除されます。いかなる場合でも、個人のIPアドレスが影響を受けないようにするために、コードにはいくつかの保護機能が組み込まれています。

実行可能にすることを忘れないでください。

sudo chmod u+x ~/externalIP.sh

関連情報