라우트를 편집해서는 전체 터널 WireGuard 호스트에서 프로그램을 예외로 뺄 수 없습니다. 라우트는 목적지로 경로를 고르는데, 예외로 빼려는 것은 프로세스이므로 커널이 비교할 대상이 없습니다. 실행 가능한 접근은 그 프로세스에 자체 네트워크 컨텍스트를 주는 것입니다. 즉 자체 인터페이스, 주소, 기본 라우트를 가진 네임스페이스를 만들고 veth 쌍으로 호스트에 연결합니다. 저는 Ubuntu 24.04에서 wireguard-tools 1.0.20210914로 이것을 실행했고, 네임스페이스는 한 번도 문제가 아니었습니다 — 호스트의 포워딩 정책과 터널의 마킹 규칙이 문제였습니다.

먼저 필요한 컨텍스트 종류를 고르십시오

실제로는 두 가지 형태가 나옵니다. 호스트가 전체 터널을 돌리고 한 프로그램만 ISP 경로로 나가야 한다면, 두 번째 네임스페이스를 만들어 호스트에 연결하고 호스트가 그를 위해 트래픽을 포워딩하고 변환하게 합니다. 네임스페이스가 이미 VPN 인터페이스를 갖고 있고 그 안에서 명령만 시작하면 된다면, 그것은 일반적인ip netns exec경우이고 라우팅 작업의 대부분은 이미 끝난 상태입니다.

어느 형태도 단일 프로세스 ID로 범위가 제한된 규칙을 주지 않습니다. Netfilter는 주소, 포트, 마크, 인터페이스를 맞추며, 프로세스별 라우팅 테이블은 없습니다. 마킹으로 트래픽을 유도할 수는 있지만, 마크는 이미 식별한 패킷에 붙여야 하고, 그것은 한 계층 아래의 같은 문제입니다. 네임스페이스는 그 프로세스 트리의 스택 전체를 분리하며, 그래서 이것이 일반적인 답입니다.

요구 사항이 정말로 터널에서 아무것도 나가지 않는 것이라면, 대신 터널을 멈추십시오. 네임스페이스는 혼합된 경우를 위한 것입니다. 프로그램 하나는 밖으로, 나머지는 모두 안으로, 같은 머신에서, 동시에.

두 번째 컨텍스트를 만들고 호스트에 연결하십시오

예시적인 배치에서는 호스트에 기본 라우트를 지닌 WireGuard 인터페이스와,clearnet라는 이름의 네트워크 네임스페이스가 있고, 이는 veth 쌍으로 호스트에 연결됩니다. 아래 주소는 예시입니다.

ip netns add clearnet
ip link add veth-clear-out type veth peer name veth-clear-in
ip addr add 192.168.100.1/24 dev veth-clear-out
ip link set veth-clear-out up
ip link set veth-clear-in netns clearnet
ip netns exec clearnet ip addr add 192.168.100.2/24 dev veth-clear-in
ip netns exec clearnet ip link set veth-clear-in up
ip netns exec clearnet ip route add default via 192.168.100.1

이 네임스페이스는 이제 호스트에만 닿을 수 있습니다. 호스트가 트래픽을 포워딩하고 출발지 주소를 다시 써야 하는 이유는 192.168.100.0/24가 사설이고 상위 라우터에는 그 안으로 돌아갈 라우트가 없기 때문입니다:

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o <wan-interface> -j MASQUERADE

더 나아가기 전에 네임스페이스 쪽을 확인하십시오.ip netns exec clearnet ip routeveth 라우트와 192.168.100.1을 통한 기본 라우트를 보여야 하고, 그 주소로의 ping이 응답해야 합니다. 호스트 주소로의 ping이 실패하면 주소나 링크 상태가 잘못된 것이며 어떤 방화벽 규칙도 도움이 되지 않습니다.

이름은 풀리는데 아무것도 돌아오지 않으면 FORWARD를 읽으십시오

전형적인 실패는 라우팅 버그처럼 보입니다. 네임스페이스가 이름을 풀고 패킷이 나가지만 응답이 끝내 오지 않습니다. FORWARD 정책이 DROP인 호스트에서는 — 여러 배포판과 대부분의 강화 이미지가 그렇게 합니다 — 패킷이 도중에 버려지고, 애플리케이션이 출력하는 오류에는 필터링에 대한 말이 없습니다.

무언가를 추가하기 전에 체인을 읽으십시오:

iptables -S FORWARD
nft list chain inet filter forward

그다음 양방향으로 트래픽을 허용하되 카운터를 붙여, 규칙이 실제로 일치한 적이 있는지 알 수 있게 하십시오:

iptables -A FORWARD -i veth-clear-out -o <wan-interface> -j ACCEPT
iptables -A FORWARD -i <wan-interface> -o veth-clear-out -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
watch -n1 'iptables -L FORWARD -v -n'

패킷 카운터가 영인 규칙은 경로에 없습니다. 인터페이스 이름이 가정과 다르거나, 체인의 앞선 규칙이 패킷을 먼저 허용, 폐기, 반환했습니다. 고칠 것은 순서이지 규칙 문구가 아닙니다.

사람들이 잊는 절반이 응답 트래픽입니다. 반환 규칙에는 같은 veth 이름과 연결 상태 일치가 필요하고, 정책을 열어 둔다면 단순한 인터페이스 허용이면 됩니다. 나가는 규칙만 추가하면 원래 증상이 그대로 돌아오고, 새 규칙은 그 자리에서 올바르게 보입니다.

터널의 마킹 규칙을 새 경로에서 멀리 두십시오

이 단계는 작동하던 네임스페이스를 새는 네임스페이스로 바꿉니다. WireGuard 설정은 보통 방화벽 마크 정책과 자체 라우팅 규칙, 전용 테이블을 설치하므로 마크가 없는 패킷은 메인 테이블로 되돌아가고 마크된 패킷은 터널 테이블을 씁니다. 네임스페이스에서 포워딩된 트래픽은 나갈 때 정책 라우팅으로 평가되며, 그 규칙이 어떻게 쓰였는지에 따라 터널 테이블로 떨어질 수 있습니다.

두 가지 추가가 경로를 분리합니다. 네임스페이스 서브넷에 대해 mangle 체인에서 일찍 돌아오고, 그 서브넷을 메인 테이블에 넣는 출발지 기반 규칙을 추가하십시오:

iptables -t mangle -I PREROUTING -s 192.168.100.0/24 -j RETURN
ip rule add from 192.168.100.0/24 lookup main priority 100

제 호스트에서는 우선순위 100이 터널 규칙보다 앞에 정렬되므로, 그 출발지에 대해서는 일반 테이블이 결정합니다. 숫자를 맹목적으로 복사하지 마십시오:wg-quick이 설치하는 우선순위는 버전과 IPv4 및 IPv6 설정에 따라 다르므로, 다음을 실행하십시오ip rule show그리고 여러분의 머신에서 터널 규칙 앞에 오는 우선순위를 고르십시오.

규칙 목록을 믿는 대신출발지별 조회로 확인하십시오:

ip route get 1.1.1.1 from 192.168.100.2
ip netns exec clearnet ip route get 1.1.1.1

첫 명령이 WireGuard 인터페이스를 보고하면 새 규칙은 아직 터널 정책 앞에 있지 않습니다. WAN 인터페이스를 보고하는데 두 번째가 여전히 veth 기본 라우트를 보여 준다면 호스트와 네임스페이스가 서로 맞지 않으므로 두 라우팅 테이블을 다시 읽어야 합니다.

연결을 여는 프로세스를 시작하십시오

명령을 시작하는 것은 한 줄이지만, 실제로 소켓을 만드는 프로세스를 시작하십시오.ip netns exec clearnet curl -s https://ifconfig.me가장 작은 정직한 테스트로, 네임스페이스가 세상에 내보이는 주소를 보여 주지 호스트가 쓸 주소가 아닙니다.

서비스라면 프로세스가 평생 그 안에 머물도록 네임스페이스를 경로로 붙이십시오:

[Service]
NetworkNamespacePath=/run/netns/clearnet

그래픽 애플리케이션은 한 줄 방식이 조용히 실패하는 곳입니다. 메뉴에서 시작한 브라우저는 이미 네임스페이스 밖에서 도는 인스턴스에 요청을 넘기는 일이 많아, 새 창은 뜨는데 트래픽은 여전히 터널로 나갑니다. 별도 프로필을 주어 새 인스턴스가 실제로 만들어지게 한 다음, 추측하지 말고 프로세스 컨텍스트를 확인하십시오:

readlink /proc/$(pgrep -f clearnet-profile | head -1)/ns/net
readlink /run/netns/clearnet

두 출력은 일치해야 합니다. 같은 점검은 오래 도는 프로그램이라면 무엇에나 쓸 수 있고, 실행기가 의도대로 했다고 가정하는 대신 애플리케이션마다 한 번씩 할 가치가 있습니다.

이름 해석에는 자체 결정이 필요합니다. 네임스페이스를 만들어도 리졸버 구성이 주어지지 않으며, 네임스페이스별 파일은 다음을 통해 지원됩니다/etc/netns/<name>/resolv.conf, 그리고 그것이 없으면 잘못 읽기 쉬운 동작을 물려받습니다. IPv6도 같은 처리가 필요합니다. 네임스페이스에 v6 기본 라우트가 없는데 애플리케이션이 v6를 선호하면 요청이 폴백 전에 멈출 수 있고, 이는 고장 난 터널처럼 보입니다.

종료 주소만이 아니라 틀을 확인하십시오

작동하는 공인 주소는 라우트를 증명할 뿐 요구 사항 전체를 증명하지 않습니다. 나머지는 이 순서로 확인하십시오:

  • ip netns exec clearnet ip route get 1.1.1.1veth 기본 라우트를 보여 주며, WireGuard 인터페이스가 아닙니다.
  • 요청이 도는 동안 두 규칙의 FORWARD 카운터가 증가합니다.
  • 애플리케이션 프로세스가 예상한 네임스페이스 inode를 보고합니다.
  • 재부팅 후에는 서비스가 시작되기 전에 네임스페이스가 존재하므로, 더 일찍 도는 unit은 실패하거나 더 나쁘게는 네임스페이스 밖에서 돕니다.

그다음 터널이 끊겼을 때 무엇이 일어나야 하는지 정하십시오. 네임스페이스는 계속 작동하며, 그것이 이 연습의 목적이자 동시에 위험입니다. 예외로 뺀 프로그램은 연결된 채로 남고 나머지는 모두 멈춥니다. 이를 정책 선택으로 기록하고 예외가 무엇을 덮지 않는지 분명히 하십시오 — 계정 신원, 저장된 브라우저 상태, DNS 제공자는 모두 네트워크 네임스페이스의 범위 밖이며, 예외를 익명성으로 취급하는 것이 구성보다 오래 사는 실수입니다.

관련 글