WireGuard 설치 및 방화벽 설정

2020-03-26

WireGuard 소개

WireGuard는 임베디드 인터페이스와 슈퍼 컴퓨터를 위한 범용 VPN로, 최첨단 암호화 기술을 사용하며 단순하고 빠르고 현대적인 VPN이다. IPsec보다 더 간단하며 더 빠르고, OpenVPN보다 성능이 훨씬 뛰어나다. 또한 Linux 5.6 커널에서 WireGuard 1.0.0 기본 패키지로 탑재되었다.

https://github.com/pirate/wireguard-docs

WireGuard 서버 설치

먼저, AWS에서 Amazon AMI Linux 2를 선택해서 EC2 서버를 생성한다. Amazon AMI Linux2에는 WireGuard 패키지가 없기 때문에 다음과 같이 리포지토리를 추가하여 설치한다.

$ curl -L -o /etc/yum.repos.d/wireguard.repo https://copr.fedorainfracloud.org/coprs/jdoss/wireguard/repo/epel-7/jdoss-wireguard-epel-7.repo

$ yum install wireguard-dkms wireguard-tools

서버에서 사용할 public 키와 private 키를 wg 유틸리티를 사용하여 생성한다.

$ wg genkey | tee privatekey | wg pubkey > publickey

$ cat privatekey
6PF4yqfeh1KSBg5N1VwEOHmF5pPIyY3f/EVSZwOxAFM=

$ cat publickey
Bhw11tUPFzyV+MWuqBQ23obspqLWN/jGpNKKJ7hvQ2I=

그리고 서버 설정 정보는 다음과 같이 /etc/wireguard/wg0.conf 파일에 저장한다. 서버 Interface항목에 에 생성된 Private Key를 기입하고, VPN Port는 1194로 설정한다.

$ cat /etc/wireguard/wg0.conf
[Interface]
Address = 172.32.100.1/32
ListenPort = 1194
PrivateKey = 6PF4yqfeh1KSBg5N1VwEOHmF5pPIyY3f/EVSZwOxAFM=
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

wg-quick 커맨드로 데몬을 실행해본다. 아직 클라이언트 Peer 정보를 구성하지 않았기 때문에, A peer is missing a public key 오류 메세지를 확인할 수 있다.

$ wg-quick up wg0
#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
A peer is missing a public key
Invalid configuration
[#] ip link delete dev wg0

다음으로 서버에서 영구적으로 IP 포워딩이 되도록 설정한다.

$ sysctl net.ipv4.conf.all.forwarding=1 | tee -a /etc/sysctl.d/forwarding.conf

이상, 시스템 부팅 시에 WireGuard가 자동 시작이 되도록 서비스에 등록하여 설치를 완료한다.

$ systemctl enable wg-quick@wg0

WireGuard 클라이언트 설치

원격 클라이언트 서버를 우분투 18.04이라고 하면, 다음과 같이 클라이언트를 구성할 수 있다.

먼저, 리포지토리를 추가한다.

$ add-apt-repository ppa:wireguard/wireguard

wireguard와 openresolv를 설치한다.

$ sudo apt install wireguard openresolv

동일하게 wg 유틸리티를 사용하여 public 키와 private 키를 생성한다.

$ wg genkey | tee privatekey | wg pubkey > publickey

클라이언트 설정 정보도 동일하게 /etc/wireguard/wg0.conf에 저장한다. 클라이언트 Interface 에 할당할 IP (예, 172.32.100.10/32)를 기입하고, 생성된 private 키를 추가한다. 그리고 Peer에는 앞서 구성한 서버 정보(공개키 값, 타겟 주소, 엔트포인트)를 입력한다.

[Interface]
Address = 172.32.100.10/24
PrivateKey = kBjlZKrmLK17sy6PyNq2cMFAQ9UUh26osb9/BzffEFU=

[Peer]
PublicKey = Bhw11tUPFzyV+MWuqBQ23obspqLWN/jGpNKKJ7hvQ2I=
AllowedIPs = 172.32.100.0/24
Endpoint = 53.125.176.231:1194
PersistentKeepalive = 5

서버와 동일하게 자동 시작이 되도록 서비스에 등록하여 설치를 완료한다.

$ systemctl start wg-quick@wg0

WireGuard 서버에 클라이언트 Peer 추가

서버에 연결될 클라이언트를 설치한 후에는, Amazon Linux AMI 2 서버에 접속하여 해당 정보를 업데이트 한다.

$ vi /etc/wireguard/wg0.conf
[Interface]
Address = 172.32.100.1/32
ListenPort = 1194
PrivateKey = OJ3K8Bb/yJemfTeLl879l/JTqHneymccEgkxr3grLG0=
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = NIk44fDwmXNSMxeYHJvYN2lIm/xUNgpXkDkBo6GjIx4=
AllowedIPs = 172.32.100.10/32

클라이언트 피어를 추가하였으므로, WireGuard 인터페이스 유틸리티로 구동시켜 본다.

$ wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 172.32.100.1/32 dev wg0
[#] ip link set mtu 8921 up dev wg0
[#] ip -4 route add 172.32.100.10/32 dev wg0
[#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

정상적으로 구동되었다면 서버를 재시작한다.

$ systemctl restart wg-quick@wg0
$ wg show
interface: wg0
  public key: Bhw11tUPFzyV+MWuqBQ23obspqLWN/jGpNKKJ7hvQ2I=
  private key: (hidden)
  listening port: 1194

peer: NIk44fDwmXNSMxeYHJvYN2lIm/xUNgpXkDkBo6GjIx4=
  endpoint: 210.224.81.99:47411
  allowed ips: 172.32.100.10/32
  latest handshake: 1 minute, 9 seconds ago
  transfer: 1.55 MiB received, 181.46 KiB sent

모든 트래픽을 VPN으로 라우팅

클라이언트의 모든 트래픽을 VPN 인터페이스 wg0으로 라우팅하려면, 다음과 같이 클라이언트 설정에서 AllowedIPs의 값을 0.0.0.0/0으로 변경한다.

[Interface]
Address = 172.32.100.10/24
PrivateKey = kBjlZKrmLK17sy6PyNq2cMFAQ9UUh26osb9/BzffEFU=

[Peer]
PublicKey = Bhw11tUPFzyV+MWuqBQ23obspqLWN/jGpNKKJ7hvQ2I=
AllowedIPs = 0.0.0.0/0
Endpoint = 53.125.176.231:1194
PersistentKeepalive = 5

그리고 wg-quick 유틸리티를 이용하여 wg0 인터페이스를 구동시킨다. 그럼, 다음과 같이 별도의 WireGuard 전용 라우팅 테이블이 생성하고, Rule 기반 라우팅이 추가되는 것을 확인할 수 있다.

$ wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 172.32.100.10/32 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] resolvconf -a tun.wg0 -m 0 -x
[#] wg set wg0 fwmark 51820
[#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
[#] ip -4 rule add not fwmark 51820 table 51820
[#] ip -4 rule add table main suppress_prefixlength 0
[#] sysctl -q net.ipv4.conf.all.src_valid_mark=1
[#] iptables-restore -n

구성된 라우팅 테이블은 각각 다음과 같다.

메인 라우팅 테이블

$ ip route show table main
default via 192.168.100.1 dev ens33 proto dhcp metric 100
169.254.0.0/16 dev ens33 scope link metric 1000
192.168.100.0/24 dev ens33 proto kernel scope link src 192.168.100.209 metric 100

로컬 라우팅 테이블

$ ip route show table local
broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
local 172.32.100.10 dev wg0 proto kernel scope host src 172.32.100.11
broadcast 192.168.100.0 dev ens33 proto kernel scope link src 192.168.100.209
local 192.168.100.209 dev ens33 proto kernel scope host src 192.168.100.209
broadcast 192.168.100.255 dev ens33 proto kernel scope link src 192.168.100.209

좀 더 자세한 내용은 WireGuard의 공식 문서 Routing All Your Traffic 을 참고한다.

방화벽 설정

마지막으로, 클라이언트에서 WireGuard VPN을 위한 방화벽 설정은 다음과 같다.

IF0="ens33"
WG0="wg0"
VPN_PORT="1194"
VPN_NET="172.32.100.0/24"

iptables -A INPUT -i $IF0 -p udp --dport $VPN_PORT -j ACCEPT
iptables -A INPUT -i $IF0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i $WG0 -j ACCEPT

iptables -A FORWARD -i $WG0 -j ACCEPT
iptables -A FORWARD -i $WG0 -o $IF0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i $IF0 -o $WG0 -m state --state RELATED,ESTABLISHED -j ACCEPT

iptables -t nat -A POSTROUTING -s $VPN_NET -o $IF0 -j MASQUERADE
iptables -A OUTPUT -o $WG0 -j ACCEPT

경로 확인

클라이언트 VPN 서버에 방화벽을 적용한 후, 다음과 같이 경로를 확인해보면 AWS 인스턴스를 통해 google.com 에 연결되는 것을 확인할 수 있다.

$ traceroute google.com
traceroute to google.com (172.217.25.78), 30 hops max, 60 byte packets
 1  172.32.100.1 (172.32.100.1)  5.458 ms  5.423 ms  5.391 ms
 2  ec2-52-80-0-92.ap-northeast-2.compute.amazonaws.com (52.80.0.92)  20.313 ms ec2-52.80.0.0.ap-northeast-2.compute.amazonaws.com (52.80.0.0)  23.326 ms ec2-52-80-0-4.ap-northeast-2.compute.amazonaws.com (52.80.0.4)  19.217 ms
 3  100.64.3.8 (100.64.3.8)  11.309 ms 100.64.3.200 (100.64.3.200)  22.228 ms 100.64.1.142 (100.64.1.142)  22.896 ms
 4  100.66.11.38 (100.66.11.38)  12.142 ms 100.66.11.166 (100.66.11.166)  10.131 ms 100.66.11.2 (100.66.11.2)  11.856 ms
 5  100.66.7.3 (100.66.7.3)  8.734 ms 100.66.7.97 (100.66.7.97)  8.989 ms 100.66.7.229 (100.66.7.229)  85.119 ms
 6  100.66.4.145 (100.66.4.145)  38.938 ms 100.66.4.99 (100.66.4.99)  7.576 ms 100.66.4.115 (100.66.4.115)  7.644 ms
 7  100.65.9.33 (100.65.9.33)  5.083 ms  4.547 ms 100.65.11.33 (100.65.11.33)  6.132 ms
 8  54.239.122.7 (54.239.122.7)  4.947 ms  7.116 ms  7.214 ms
 ...

Yeongpil Yoon

Powered by Hugo & Kiss.