2P by GN⁺ | ★ favorite | 댓글 1개
  • Wireproxy는 WireGuard 피어에 연결한 뒤 로컬 머신에서 SOCKS5/HTTP 프록시나 터널로 노출되는 완전한 사용자 공간 WireGuard 클라이언트임
  • 새 네트워크 인터페이스를 설정하지 않고 특정 사이트 트래픽만 WireGuard 피어로 보내고 싶거나, WireGuard 설정 변경에 root 권한을 쓰고 싶지 않은 경우를 겨냥함
  • 기능은 TCP 정적 라우팅, SOCKS5/HTTP 프록시, TLS SNI 기반 투명 프록시를 포함하며, HTTP 프록시는 현재 CONNECT만 지원함
  • 설정은 wg-quick[Interface], [Peer] 의미를 따르고, 기존 WireGuard 설정 파일을 WGConfig로 가져오거나 여러 피어를 AllowedIPs로 라우팅할 수 있음
  • 운영용으로 --info/-i 기반 health endpoint를 제공하며 /metrics/readyz로 WireGuard 상태와 CheckAlive 기반 준비 상태를 확인할 수 있음

Wireproxy가 하는 일

  • wireproxy는 WireGuard 피어에 연결하고, 로컬 머신에 SOCKS5/HTTP 프록시 또는 터널을 노출하는 사용자 공간 애플리케이션임
  • 특정 사이트만 WireGuard 피어를 통해 접속하고 싶지만 새 네트워크 인터페이스를 만들고 싶지 않을 때 사용할 수 있음
  • 네트워크 인터페이스와 완전히 분리되어 동작하며, 설정을 위해 root 권한이 필요하지 않음
  • Amnezia VPN과 유사한 용도가 필요한 사용자는 wireproxy-awg 포크를 사용할 수 있음

지원 기능과 아직 없는 기능

  • 지원 기능
    • 클라이언트와 서버용 TCP 정적 라우팅
    • SOCKS5/HTTP 프록시
      • HTTP는 현재 CONNECT만 지원함
    • Server Name Indication을 사용하는 투명 TLS 프록시
  • TODO로 남은 기능
    • SOCKS5의 UDP 지원
    • UDP 정적 라우팅

실행과 설치

  • 기본 실행 형식은 ./wireproxy [-c path to config]
  • 주요 옵션
    • -c, --config: 설정 파일 경로 지정
      • 기본 경로는 /etc/wireproxy/wireproxy.conf, $HOME/.config/wireproxy.conf
    • -s, --silent: silent mode
    • -d, --daemon: 백그라운드 실행
    • -i, --info: health status 노출용 주소와 포트 지정
    • -v, --version: 버전 출력
    • -n, --configtest: 설정 파일 유효성만 확인
  • 빌드는 저장소를 클론한 뒤 make로 수행함
  • 설치 예시는 go install github.com/windtf/wireproxy/cmd/wireproxy@v1.1.2 또는 @latest를 사용함

설정 모델

  • [Interface][Peer] 설정은 wg-quick 설정과 같은 의미를 따름
  • Address는 IPv4의 경우 /32, IPv6의 경우 /128 서브넷을 사용해야 함
  • PrivateKey는 환경 변수 참조도 가능함
  • 기존 WireGuard 설정이 있다면 WGConfig = <path to the wireguard config>로 가져올 수 있음

터널과 프록시 설정

  • TCPClientTunnel
    • 로컬 머신에서 수신한 TCP 트래픽을 WireGuard를 통해 지정 대상에 전달함
    • 예시 흐름은 <LAN 앱> → localhost:25565 → WireGuard → play.cubecraft.net:25565
  • TCPServerTunnel
    • WireGuard 네트워크에서 수신한 TCP 트래픽을 로컬 네트워크의 지정 대상으로 전달함
    • 예시 흐름은 <WireGuard 네트워크 앱> → WireGuard → 172.16.31.2:3422 → localhost:25545
  • STDIOTunnel
    • wireproxy 프로세스의 표준 입력과 출력을 WireGuard 경유 TCP 대상에 연결함
    • opensshProxyCommand 파라미터로 쓰기 유용함
  • Socks5
    • 로컬 LAN에 SOCKS5 프록시를 만들고 모든 트래픽을 WireGuard로 라우팅함
    • 사용자 이름과 비밀번호를 지정하면 프록시 인증을 활성화함
  • http
    • 로컬 LAN에 HTTP 프록시를 만들고 모든 트래픽을 WireGuard로 라우팅함
    • 사용자 이름과 비밀번호를 지정하면 인증을 활성화함
    • CertFileKeyFile을 지정하면 HTTPS를 활성화함
  • SNI
    • 로컬 LAN에 투명 TLS 프록시를 만들고, SNI를 라우팅 목적지로 사용해 WireGuard를 통해 트래픽을 보냄

여러 피어와 라우팅

  • 여러 WireGuard 피어를 사용할 수 있음
  • 여러 피어를 쓸 때는 wireproxy가 어느 피어로 전달할지 알 수 있도록 AllowedIPs를 지정해야 함
  • 설정 예시는 서로 다른 AllowedIPs를 가진 여러 [Peer]와 여러 TCPServerTunnel을 함께 사용함
  • UDPProxyTunnel 예시도 포함됨
    • BindAddress로 로컬 바인드 주소를 지정함
    • Target으로 대상 주소를 지정함
    • InactivityTimeout0이면 타임아웃하지 않음
  • [Resolve]는 DNS 해석 전략을 설정함
    • ipv4: A 레코드를 우선함
    • ipv6: AAAA 레코드를 우선함
    • auto: 기본값이며, WireGuard 인터페이스가 IPv4 주소만 가지면 ipv4와 같고 그렇지 않으면 ipv6와 같음
  • Endpoint가 없는 [Peer] 설정으로 피어가 wireproxy에 연결하도록 허용할 수 있음

Health endpoint

  • --info/-i는 예를 들어 localhost:9080 같은 주소와 포트를 받아 health status metric을 제공하는 HTTP 서버를 노출함
  • 현재 두 endpoint가 구현되어 있음
    • /metrics: WireGuard 데몬 정보를 노출하며 wg show와 같은 정보를 제공함
    • /readyz: CheckAlive에 지정된 IP에서 마지막으로 pong을 받은 시간을 JSON으로 반환함
  • CheckAlive가 설정되면 지정된 주소로 CheckAliveInterval초마다 WireGuard를 통해 ping을 보냄
    • 기본 CheckAliveInterval은 5초임
    • 마지막 CheckAliveInterval초에 지연 여유 2초를 더한 시간 안에 pong을 받지 못하면 503을 반환함
    • 조건을 만족하면 200을 반환함
  • CheckAlive가 설정되지 않은 경우 /readyz는 빈 JSON 객체와 200을 반환함
  • ICMP ping 패킷이 라우팅되는 피어는 각 피어의 AllowedIPs 설정에 따라 달라짐

댓글과 토론

Hacker News 의견들
  • 작은 도구지만 훌륭함. Firefox의 multi-account containers로 특정 탭만 골라, WireGuard는 지원하지만 애플리케이션 계층 프록시나 SSH는 없는 홈 라우터로 프록시하는 데 쓰고 있음

    • multi-account containers가 컨테이너별 프록시 설정을 지원한다는 걸 처음 알았음
      이걸 설정하려면 https://addons.mozilla.org/en-GB/firefox/addon/container-pro... 같은 별도 확장이 필요한 줄 알았는데, 아니었고 이제는 그런 착각도 다운보트 사유가 되는 듯함
    • 이런 구성을 어떻게 설정하는지 설명한 좋은 자료가 있으면 궁금함
  • WireGuard로 하려던 작업에는 https://github.com/dariost/soks가 더 잘 맞았음. 거의 같은 일을 하지만 기존 WireGuard 인터페이스를 재사용함
    사용 방식은 이 글에 자세히 적었음: https://www.nicoco.fr/blog/2023/09/10/wireguard/

    • 이건 꽤 다름. wireproxy는 사용자 공간에서 TCP와 WireGuard 구현을 포함하는 것처럼 보이고, soks는 TCP만 처리할 수 있는 IP 라우터에 가까움
      라우팅 테이블을 제어 수단으로 쓰는 대신 SOCKS5 프록시를 쓸지 말지 결정하는 방식으로 보임
    • 왜 그쪽이 더 잘 맞았는지 궁금함
      예전에는 Raspberry Pi의 Docker 컨테이너로 비슷하게 했지만, 어떤 운영체제에서든 실행 가능하고 호스트의 라우팅 테이블을 실수로 망치지 않는다는 보장이 있어서 사용자 공간 해법이 훨씬 나은 선택으로 보임
  • onetun도 있음: https://github.com/aramperes/onetun

  • 완전히 사용자 공간 서버 구현도 있는지 궁금함. tun/tap 장치 없이 하려면 사용자 공간 IP 스택 같은 게 필요할 것 같긴 한데 확실하진 않음

  • 다른 IP가 필요할 때 쓰던 SSH 터널을 대체하기에 좋겠음
    관련 도구로 pproxy도 있는데, 여러 기능 중 하나로 서로 다른 터널 프로토콜을 “변환”할 수 있고 라우팅 기능도 있음. SSH SOCKS5를 HTTP 프록시로 바꾸는 데 썼음: https://github.com/moreati/pproxy

  • “이런 건 Go로 꽤 쉽게 만들 수 있겠는데?”라고 생각했는데, 역시 Go로 작성되어 있었음

  • 여러 다중 프로토콜 프록시 클라이언트가 이 기능을 지원함. 대표적인 오픈소스 예로 sing-box, clash-meta 및 다른 clash 기반 클라이언트, xray가 있음
    비공개 소스 클라이언트로는 Surge Mac/iOS가 있음

    • 맞는 말임. 이런 다중 프로토콜 프록시들은 아마 중국 방화벽 우회를 위해 만들어졌을 텐데, 흥미로운 작은 생태계임
      잘 알려지지 않은 트래픽 라우팅 가능성이 많고 Android 구현도 있음. 예전에 핫스팟을 지원하지 않는 SIM과 루팅하지 않은 Android에서 핫스팟을 열려고 써봤음
      다만 인터넷 여기저기서 가져온 코드가 많이 들어 있고 개발자 커뮤니티도 여러 이유로 꽤 특이해서, 얼마나 신뢰할 수 있는지는 늘 궁금함
    • 비공개 소스 쪽에서는 Cloudflare WARP도 프록시 모드로 동작할 수 있음. WARP 설정을 일반 WireGuard 설정으로 변환하면 무료 계정도 이렇게 쓸 수 있음
    • 중국에서 안정적으로 동작하는 건 clash + v2ray가 거의 유일해 보임. 대부분의 대형 VPN 업체가 중국에서 된다고 하지만 실제로는 안 됨
      작동 방식을 깊이 파보진 않았지만, 어떤 도메인을 VPN으로 프록시할지 규칙 그룹으로 결정하는 개념은 마음에 듦
  • 성능이 궁금함. 기억으로는 “바닐라” SOCKS는 설정이 아주 쉽지만, 즉 SSH를 적절한 옵션으로 실행하고 애플리케이션에 쓰라고 알려주면 되지만, 꽤 느렸음
    이 도구는 일반 SOCKS/SSH 서버가 없는 경우를 위한 것 같지만, 그쪽에서도 이점이 있는지 궁금함

    • “바닐라” SOCKS가 무슨 뜻인지 궁금함. 어떤 다른 SOCKS 구현과 대비하는 말인지 모르겠음
      내 경우 SSH 위의 SOCKS는 늘 성능이 꽤 좋았고, OpenSSH의 TUN 모드처럼 TCP 위에 TCP를 얹게 되는 방식과는 달랐음
    • 둘을 비교해보면 좋겠음. 지금은 WireGuard에 연결한 뒤 SSH로 SOCKS 프록시를 만들고 있고, 의외로 잘 동작함
      그래도 이 해법에는 매우 관심이 있음
  • Thunderbird의 모든 이메일 연결을 Tailscale exit node를 통해 프록시하되, 전체 트래픽을 exit node로 보내지는 않게 하는 도구가 있으면 좋겠다고 막 생각하던 참이었음

    • tailscale CLI를 SOCKS 프록시로 쓸 수 있음: https://tailscale.com/kb/1113/aws-lambda
      이걸 컨테이너 이미지에 넣고 tailscale이 듣는 SOCKS 포트를 노출하면 바로 프록시가 됨
    • exit node가 실행 중인 머신에 3proxysquid proxy를 설치해도 됨. tailnet에 있는 모든 머신이 그걸 볼 수 있음
  • Mullvad VPN 전용으로 이런 게 필요하다면 https://github.com/imiric/mullvad-proxy를 써보고 좋았음
    내 프로젝트는 아니고 업데이트용으로 포크만 했음. 좋은 점은 Mullvad CLI 도구를 내장해서 서버 전환이 아주 쉽고, 전부 호스트 머신과 격리된다는 것임. 또한 “그냥” nginx와 몇몇 스크립트라서 SOCKS5 지원도 괜찮을 것 같음