VPN을 통한 NAT 리플렉션을 통한 외부 웹 서비스 액세스 시간 초과

VPN을 통한 NAT 리플렉션을 통한 외부 웹 서비스 액세스 시간 초과

Strongswan VPN 서버와 여러 서비스를 실행하는 Raspbian arm64가 있는 Raspberry Pi 4B가 있고 외부 IP/도메인 이름을 통해 흐름 WAN에 액세스할 수 있습니다. LAN에서 동일한 서비스를 사용할 수 있도록 라우터에서 NAT 리플렉션을 사용합니다. 모든 VPN 장치에서 인터넷과 LAN의 모든 장치에 액세스할 수 있으므로 VPN 라우팅이 제대로 작동하는 것 같습니다. 마찬가지로 LAN에서 모든 VPN 장치에 ping을 보낼 수 있습니다.

내 도메인 이름을 통해 내 웹 서비스에 액세스하려고 하면 문제가 발생합니다. 일반적으로 LAN 및 WAN에서 액세스할 수 있는 동일한 서비스를 VPN 장치에서는 액세스할 수 없습니다. LAN에 있는 다른 장치의 포트를 전달하고 도메인 이름을 통해 VPN 장치의 포트에 액세스하려고 하면 제대로 작동합니다. 따라서 라우팅 및 NAT 반사는 내 네트워크 설정에 적합한 것 같습니다. VPN과 동일한 서버에 있는 도메인/외부 IP를 통해 웹 사이트에 액세스하려고 할 때만(로컬 IP를 통해 웹 사이트에 액세스하면 문제 없음) 예상대로 작동하지 않습니다.

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 주소를 통해 이 서버 이외의 장치에 거의 액세스하지 않기 때문에 이러한 타협을 기꺼이 받아들입니다. 그러나 이 점을 인지하고 이것이 귀하의 상황에도 적용되는지 확인해야 합니다.

이를 달성하기 위해 두 개의 위치 매개변수(공용 IP 주소를 할당하려는 인터페이스와 도메인 이름)를 허용하는 bash 스크립트를 작성했습니다. 예를 들어 사용법은 다음과 같습니다.

sudo ~/externalIP.sh eth0 example.com

이 스크립트는 시작 시 실행되어야 하며 IP 주소가 변경되는 경우 주기적으로 실행되어야 합니다. 예를 들어 루트 사용자의 crontab을 사용하여 스크립트를 루트에서 실행하는 것이 중요합니다.

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

관련 정보