12개 구축

실제로 라우팅되는 IPv6가 있는 강화된 WireGuard 서버

클라이언트에게 프라이빗 v4 주소와 실제로 라우팅되는 IPv6 접두사를 제공하는 WireGuard 엔드포인트를 구축하고, 요청하지 않은 모든 것을 차단하는 nftables 정책을 적용합니다.

이 문서가 만드는 것

WireGuard를 실행하는 인스턴스 하나가 모든 클라이언트에 사설 IPv4 주소, 자체 /48에서 가져온 라우팅된 IPv6 주소, 그리고 터널 내부에 위치하여 DNS 쿼리가 다른 트래픽과 다른 경로를 타지 않도록 하는 리졸버를 제공합니다. 방화벽은 양방향 모두 기본 차단입니다. 포워딩은 터널 인터페이스에서만, 그리고 아웃바운드로만 활성화됩니다.

AMS-01의 R-4에서 Debian 13으로 테스트했습니다. WireGuard는 단일 흐름의 커널 측 구현이므로, 멀티기가비트를 푸시하기 전에는 코어가 많아도 이득이 없습니다. 훨씬 더 중요한 것은 사이트 선택입니다. 실제로 있는 곳과 가장 가까운 사이트를 고르세요. 여기서 추가하는 모든 밀리초는 모든 패킷에 추가됩니다.

시작하기 전에

  • 배포된 인스턴스와 SSH 루트 접근.
  • 패널에서 IPv6 /48 애드온 활성화. 포함된 /64는 단일 클라이언트에 작동하지만, 단일 /64에서 클라이언트별 서브넷을 사용하려면 이웃 탐색을 프록시해야 하며, 이는 구성이라기보다 취미에 가깝습니다.
  • 인스턴스를 가리키는 호스트 이름. 아래 모든 항목은 vpn.example.com을 사용합니다.
  • 여기의 모든 2001:db8: 주소는 문서용 공간입니다. 인스턴스 페이지에 표시된 접두어로 바꾸세요.

1. 패키지 및 커널 설정

apt update && apt full-upgrade -y
apt install -y wireguard-tools nftables unbound qrencode
ip -br link

마지막 명령은 외부 인터페이스 이름을 출력합니다. KVM 이미지에서는 ens3입니다. 다르다면 아래 모든 곳에서 바꾸세요. 이제 커널:

cat > /etc/sysctl.d/99-wireguard.conf <<EOF
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.ens3.accept_ra = 2
net.ipv4.conf.all.rp_filter = 1
EOF
sysctl --system

accept_ra = 2 라인은 사람들이 잊는 부분입니다. IPv6 포워딩을 켜면 커널이 라우터 알림 수신을 중단하고, 기본 경로가 10분 이내에 사라지며, v4로는 응답하면서 v6로는 깜깜해집니다. 값을 2로 설정하면 포워딩 호스트에서 알림 수신을 계속합니다.

2. 키

install -d -m 700 /etc/wireguard
umask 077
wg genkey | tee /etc/wireguard/server.key | wg pubkey > /etc/wireguard/server.pub
wg genkey | tee /etc/wireguard/laptop.key | wg pubkey > /etc/wireguard/laptop.pub
wg genpsk > /etc/wireguard/laptop.psk

사전 공유 키는 이 구성에서 선택 사항이 아닙니다. 비용은 없고 각 구성에 한 줄일 뿐이며, 지금은 안전하지만 나중에 해독하기 위해 지금 트래픽을 기록하는 적에 대해서도 안전한 터널을 만드는 차이입니다.

3. 서버 인터페이스

/etc/wireguard/wg0.conf을 작성하고 표시된 위치에 키 내용을 붙여넣으세요:

[Interface]
Address = 10.7.0.1/24, 2001:db8:1a2b:7::1/64
ListenPort = 51820
PrivateKey = <contents of /etc/wireguard/server.key>
MTU = 1420

[Peer]
# laptop
PublicKey = <contents of /etc/wireguard/laptop.pub>
PresharedKey = <contents of /etc/wireguard/laptop.psk>
AllowedIPs = 10.7.0.2/32, 2001:db8:1a2b:7::2/128

서버 측에서 AllowedIPs은 권한 목록이 아닌 라우팅 테이블입니다. 각 피어에게 정확히 소유한 주소만, 더 넓게는 주지 마세요. 그렇지 않으면 두 클라이언트가 같은 경로를 놓고 싸우고 패자는 패킷 수신을 중단합니다.

chmod 600 /etc/wireguard/wg0.conf

4. 터널 내부의 리졸버

클라이언트를 공용 리졸버로 지정하면 목적의 상당 부분이 무효화됩니다. Unbound가 이미 설치되어 있습니다. /etc/unbound/unbound.conf.d/tunnel.conf을 지정하세요:

server:
  interface: 10.7.0.1
  interface: 2001:db8:1a2b:7::1
  access-control: 10.7.0.0/24 allow
  access-control: 2001:db8:1a2b:7::/64 allow
  do-ip6: yes
  prefetch: yes
  hide-identity: yes
  hide-version: yes
  qname-minimisation: yes

터널이 존재하기 전에는 해당 주소가 아직 올라오지 않았으므로 Unbound는 시작하지 못합니다. 싸우지 말고 제대로 순서를 정하세요:

systemctl edit unbound
[Unit]
[email protected]
[email protected]

5. 방화벽

/etc/nftables.conf을 완전히 교체하세요:

flush ruleset

table inet filter {
  chain input {
    type filter hook input priority filter; policy drop;
    ct state established,related accept
    ct state invalid drop
    iif lo accept
    ip protocol icmp accept
    ip6 nexthdr icmpv6 accept
    tcp dport 22 accept
    udp dport 51820 accept
    iifname "wg0" udp dport 53 accept
    iifname "wg0" tcp dport 53 accept
  }
  chain forward {
    type filter hook forward priority filter; policy drop;
    ct state established,related accept
    iifname "wg0" oifname "ens3" accept
    iifname "wg0" oifname "wg0" drop
  }
  chain output {
    type filter hook output priority filter; policy accept;
  }
}

table ip nat {
  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    ip saddr 10.7.0.0/24 oifname "ens3" masquerade
  }
}

없는 것이 무엇인지 주목하세요: IPv6용 NAT 테이블이 없습니다. 클라이언트는 /48에서 가져온 자체 주소로 이그레스하며, 이것이 /48을 취하는 전부입니다. iifname "wg0" oifname "wg0" drop 라인은 피어 간 연결을 막습니다. 의도적으로 메시를 구축하지 않는 한 원하는 것입니다.

systemctl enable --now nftables
nft list ruleset | head -20

6. 시작

systemctl enable --now wg-quick@wg0
systemctl restart unbound
wg show wg0

7. 클라이언트

[Interface]
PrivateKey = <contents of /etc/wireguard/laptop.key>
Address = 10.7.0.2/24, 2001:db8:1a2b:7::2/64
DNS = 10.7.0.1
MTU = 1420

[Peer]
PublicKey = <contents of /etc/wireguard/server.pub>
PresharedKey = <contents of /etc/wireguard/laptop.psk>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

전화의 경우 서버에서 QR 코드로 바꾸고 터미널을 촬영하세요:

qrencode -t ansiutf8 < /root/laptop.conf

Debian 또는 Ubuntu 클라이언트에서 DNS = 라인은 openresolv 설치가 필요합니다. 그렇지 않으면 wg-quick이 경고를 출력하고 기존 리졸버를 조용히 남겨둡니다. 완벽하게 작동하면서 모든 조회를 누출하는 터널의 가장 흔한 원인입니다.

확인

순서대로 네 가지 확인. 실패한 항목은 어느 단계로 돌아가야 하는지 알려줍니다.

# on the server, after connecting the client
wg show wg0 latest-handshakes
wg show wg0 transfer

지난 2분 이내의 핸드셰이크 타임스탬프와 양방향 0이 아닌 카운터는 암호화와 라우팅이 모두 정상임을 의미합니다.

# on the client
ping -c3 10.7.0.1
ping -c3 2001:db8:1a2b:7::1
dig @10.7.0.1 paragonvps.com AAAA +short

세 번째 명령은 터널 리졸버가 응답한다는 것을 증명합니다. 시간 초과되면 wg0이 존재하기 전에 unbound가 시작된 것입니다. 다시 시작하세요.

마지막 확인만 트래픽이 생각한 곳에서 나가는지 증명하며, 두 번째 머신이 필요합니다. 다른 도시의 플릿 내 다른 인스턴스면 충분합니다:

# on the second instance
nc -lv 9101

# on the client, tunnel up
curl -m5 -4 http://second.example.com:9101/
curl -m5 -6 http://second.example.com:9101/

리스너는 각 연결의 소스 주소를 출력합니다. v4 시도는 마스커레이드되었으므로 WireGuard 서버에서 도착해야 합니다. v6 시도는 /48 내 클라이언트 자체 터널 주소에서 도착해야 하며, 이는 라우팅되며 프록시되지 않는 것을 의미합니다.

문제 발생 시

증상원인해결책
핸드셰이크 성공, 트래픽 없음포워딩 꺼짐 또는 포워드 체인 차단sysctl net.ipv4.ip_forward 후 포워드 체인 다시 읽기
작은 요청 정상, 큰 다운로드 멈춤MTU 및 경로 탐색두 구성 모두 MTU = 1380로 낮추고 재시도
부팅 후 약 10분에 IPv6 사라짐포워딩이 라우터 알림 종료외부 인터페이스에서 accept_ra = 2
터널 외부에서 DNS 해석클라이언트가 DNS = 무시클라이언트에 openresolv 설치
재부팅 후 모두 사라짐유닛 활성화 안 됨systemctl enable wg-quick@wg0 nftables unbound

여기서 합리적인 다음 단계는 다른 지역의 두 번째 엔드포인트와 하나가 응답을 멈출 때 알려주는 모니터링 스택입니다. 둘 다 가이드의 다른 곳에서 다룹니다. 네트워크 페이지는 에지가 트래픽을 처리한 후 도달하기 전에 무엇을 하는지 설명합니다.

준비 완료

도시를 고르고, 크기를 고르고, 코인으로 결제하세요.

신원 확인 양식도, 승인을 기다리는 담당자도, 검증을 위한 전화도 없습니다. 청구서가 결제되면 자격 증명이 받은 편지함에 도착합니다.