WireGuard 설치

WireGuard 설치

요약: Proxmox + LXC 사용하여 WireGuard를 docker로 설치 방법 정리

Proxmox 설정

현재 사용하고 있는 Proxmox 7.2-7에서는 LXC에서 WireGuard를 실행할 때 필요한 /dev/net/tun을 사용하지 못한다. 이는 두가지 문제로 인한 것인데:

  1. /dev/net/tun이 LXC와 바인딩이 안 되어있고,
  2. LXC에서 /dev/net/tun을 사용하기 위한 권한 설정이 잘 못되어있다.

LXC는 보안으로 인해 unprivileged로 실행된다. 물론 privileged로도 실행 가능하지만 최대한 가능하면 unprivileged로 실행하고 싶었다. 이를위해 아래와 같이 LXC config를 수정하여 LXC에서 사용할 수 있도록 한다. 우선 실행 중인 LXC를 종료시키고 Proxmox의 shell로 들어간다. 102는 WireGuard를 설치하고자 하는 LXC ID이다.

$ vi /etc/pve/lxc/102.conf

# Add the following lines at the end
lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net dev/net none bind,create=dir

추가적으로 /dev/net/tun의 권한도 수정한다. 수정 후 Proxmox에서는 owner가 100000:100000으로 보이고, LXC안에서는 root:root로 보인다. 하지만 수정 후 Proxmox를 재시작하면 수정했던 권한이 원복된다. 재시작 후 WireGuard는 잘 동작하기에 이부분 수정이 정말 필요한 부분인지는 다음에 다시 WireGuard 설정할 때 테스트해 봐야겠다.

$ chown 100000:100000 /dev/net/tun
Check the permissions are set correctly:
# ls -l /dev/net/tun crw-rw-rw- 1 100000 100000 10, 200 Dec 22 13:26 /dev/net/tun

LXC 설정

WireGuard는 wg-easy 버전를 사용한다. linuxserver 버전과 비교하여 wg-easy 버전은 peer에서 필요한 인증서를 GUI를 통해 쉽게 발급할 수 있게 해준다. 이는 linuxserver 버전과 비교 시 매우 큰 장점이였다.

다음과 같이 docker-compose.yml 작성한다. 기본 docker-compose.yml에서 필요한 부분 몇개를 수정했다. 특히 WG_ALLOWED_IPS가 어려웠는데, 여기에는 VPN을 통해 접속할 수 있는 네트워크 IP 주소를 적어야한다. 예를 들어:

  • 192.168.0.0/24 로 작성할 경우 VPN을 통해 private IP인 192.168.0.0/24 주소를 접속할 수 있다. 그 외에는 client에서 기본으로 사용하는 네트워크, 예를 들어 핸드폰의 LTE/Wifi 네트워크를 사용한다.
  • 0.0.0.0/0 로 작성할 경우 모든 IP주소는 VPN을 통해 접속한다. 예를 들어 핸드폰에서 사용하는 모든 인터넷 패킷은 VPN을 통해 전송된다.

그외 WireGuard 옵션에 대한 설명은 wg-easy 페이지를 참고하자.

wget https://raw.githubusercontent.com/WeeJeWel/wg-easy/master/docker-compose.yml
version: "3.8"
services:
  wg-easy:
    environment:
      # Required:
      # Change this to your host's public address
      - WG_HOST=vpn.rhchoi.com

      # Optional:
      # - PASSWORD=foobar123
      # - WG_PORT=51820
      # - WG_DEFAULT_ADDRESS=10.8.0.x
      - WG_DEFAULT_DNS=1.1.1.1
      # - WG_MTU=1420
      - WG_ALLOWED_IPS=192.168.0.0/24, 10.0.1.0/24
      # - WG_PRE_UP=echo "Pre Up" > /etc/wireguard/pre-up.txt
      # - WG_POST_UP=echo "Post Up" > /etc/wireguard/post-up.txt
      # - WG_PRE_DOWN=echo "Pre Down" > /etc/wireguard/pre-down.txt
      # - WG_POST_DOWN=echo "Post Down" > /etc/wireguard/post-down.txt

    image: weejewel/wg-easy
    container_name: wg-easy
    volumes:
      - ./data:/etc/wireguard
    ports:
      - "51820:51820/udp"
      - "51821:51821/tcp"
    restart: unless-stopped
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    sysctls:
      - net.ipv4.ip_forward=1
      - net.ipv4.conf.all.src_valid_mark=1

docker compose를 사용하여 실행하고, 51821에 접속하여 키를 발급 받는다.

$ docker compose up -d

핸드폰에서 WireGuard 앱을 받고, 키를 import하고 접속하면 된다.

Troubleshooting

Odroid HC2에 WireGuard를 처음 설치했을 시의 에러 메세지:

$ docker ps -a
CONTAINER ID   IMAGE  ...
5edefe670443   weejewel/wg-easy:nightly ...
...
$ docker logs 5edefe670443
2022-09-06T13:51:37.991Z Server Listening on http://0.0.0.0:51821
2022-09-06T13:51:37.996Z WireGuard Loading configuration...
2022-09-06T13:51:38.000Z WireGuard Configuration loaded.
2022-09-06T13:51:38.001Z WireGuard Config saving...
2022-09-06T13:51:38.005Z WireGuard Config saved.
$ wg-quick down wg0
$ wg-quick up wg0
Error: WireGuard exited with the error: Cannot find device "wg0"
This usually means that your host's kernel does not support WireGuard!
    at /app/lib/WireGuard.js:65:19
    at async /app/lib/WireGuard.js:63:9

설치된 kernel은:

$ uname -a
Linux odroid 5.4.211-407 #1 SMP PREEMPT Fri Aug 26 16:27:02 UTC 2022 armv7l armv7l armv7l GNU/Linux

5.6 kernel 이하 버전에 모듈을 추가하여 WireGuard 설치하는 방법도 있는 것 같다. 하지만 이제는 x86_64 서버로 이전하였기에 더이상 Odroid에 설치할 필요가 없어 시도는 안 해봤다.