Wireguard 설치/설정 : Ubuntu/Openwrt/Android/iOS

tl;dr
이 글은 너무 길고, 나중에 다시 보면 짜증이 날 가능성이 높다.
따라서 다른 글에 설정만 따로 정리했다.


이 모든 일은 Chrome Cast 로 인해 비롯됐다. 외부에 있을 때, 집에 있는 크롬캐스트를 조작할 수 있는 방법이 없을까를 고심했는데, 그러다가, 혹시 VPN 을 사용하면 되지 않을까? 하는 생각을 하게 되었고, 결국 Wireguard 까지 오게됐다.

그러나, Wireguard 를 사용한다해도, 크롬 캐스트를 외부에서 조작할 수는 없다. 내부 기기로 접근은 가능하지만, 크롬 캐스트 사용은 불가능하다. 이게 되려면 구글 홈에서 크롬 캐스트를 인식해야 하는데, 구글 홈은 와이파이가 떠 있어야만 작동을 하는 듯 하다.

그런데, 나는 이동통신망을 이용해 Wireguard VPN 으로 접속했기 때문에, 구글 홈의 기본 조건조차 만족시키질 못한다.
혹, 외부 Wifi 로 접속한 뒤 VPN 으로 접속하면 될 지는 모르겠지만, 외부에서 원할 때에 바로 Wifi 를 찾을 수 있는 게 아니기 때문에, 이 방법은 된다해도 큰 의미가 없다.

따라서, 외부에서 크롬 캐스트를 이용하는 (지금까지 찾은) 최선의 방법은, 크롬 원격 데스크톱이 유일하다.

서론은 여기까지.
이제 본격 설치에 들어가본다.


이걸 하느라고 꽤 많은 문서를 봤는데, 내가 원하는 상황까지 되게 해준 방법을 찾기가 어려웠다. 네트웍에 대해 지식이 풍부하지 못한 탓이리라.

내가 VPN 을 사용하려고한 목적(?) 및 환경은 다음과 같다.

내부 네트웍은 192.168.1.0/24 대역을 사용하고 있고, 공유기가 물려있다. 공유기는 IPTime 제품이라 Wireguard 를 직접 설치하기는 불가능하다. (그래서 결국 Openwrt 가 지원되는 공유기를 사용할 예정이다.)
따라서, 일단은 VirtualBox 에 우분투 서버(Bridge 네트웍을 통해 192.168.1.x 할당)를 설치해서 Wireguard 를 시험해봤고, 마찬가지로 큐비트럭에 Openwrt 를 올려서 작동상태를 확인했다.

이 글에선 우분투서버와 Openwrt 에 ‘서버’ 역할을 하는 Wireguard 설치에 대해 정리해보고, 클라이언트 입장에선 우분투, Android, iOS 기기에서 설정법을 알아본다.

0. 기본

사실, 내겐 굳이 Wireguard 를 쓸 이유는 없다. 집에 있는 기기에 접속하는게 주 목적인데, 공유기에서 그 기기로만 Port Forward 를 해놓으면 ssh 접속이 되므로, VPN 이 반드시 필요하지는 않다.

물론, 접속해야할 기기가 여러 대라면 기기별 Port Forward 보다는 VPN 을 이용하는 편이 훨씬 편하긴 하겠다.

어쨌든, 현재 세상에 나와있는 VPN 중, 손쉽게 구할 수 있는 VPN 은 OpenVPN 과 Wireguad 2종류다. OpenVPN 은 어떤 방식을 쓰는지 모르지만, Wireguard 는 공개키암호화에 기반하고 있다.
따라서, 반드시 키교환이 이뤄져야 하며, 서버든 클라이언트든 공개키쌍을 생성해야만 한다. Wireguard 사용에는 이 개념이 가장 중요하다.

그리고 Wireguard 는 리눅스 5.6 커널부터는 아예 커널 자체에 포함된다고 하며, 그에 따라 리눅스 기기에서는 기본으로 사용할 수 있게된다고 한다. 지금 당장은 커널 모듈(DKMS) 형식으로 제공되고 있다.

OpenVPN 과 비교하여, 신기술에, 오픈소스에 Free 소프트웨어이고, 커널에서 바로 지원되며, 그런 저런 이유로 인해 속도가 훨씬 빠르다는 게 장점이라고 한다. 어느 정도일지는 내 능력 밖. (OpenVPN 도 Open-source 이기는 하지만, 상용이며, 커뮤니티 판으로 무료 사용이 가능하다.)

우분투의 경우, 18.04 에서 설치하면 이를 위해 특화된 커널(현재 5.3.0-1026-gke)이 설치되는데, 이게 정확히 뭔지는 잘 모르겠다. 아마도 커널 5.6 이 되면, 그냥 일반 커널에서도 될 듯은 한데.. 우분투 20.04 도 아직은 5.4 에 머물고 있으므로, 5.6 은 아직은 먼 곳의 얘기다.

사용 환경 (공유기에서 UDP Port Forward 필요)

다음 상황을 가정했다.

  • 공유기 (192.168.1.1 및 공인 IP)
  • Wireguard 서버 (192.168.1.2)
  • 클라이언트/랩탑 (외부 환경에서 접속)
  • 클라이언트/휴대기기 (Android, iOS)

Openwrt 는, 아직 공유기로 사용해보지는 않았기 때문에, 공유기로서 사용할 Openwrt 에 대한 설정은 나중에 추가하기로 한다.

그리고, 이 상황에서, 외부 기기로부터 Wireguard 서버(192.168.1.2)로 접속을 하려면, 공유기에서 서버로 포트 포워드를 해줘야 한다. 포트 번호는 설정하기 나름이고, 종류는 UDP 다.

1. 서버 설치

1.1 Ubuntu 에서.

저장소 추가 및 설치

** 길을 제시해준 Stavros Korokithakis 에게 감사를. (물론, 그도 어디선가 얻은 지식인지는 모르겠으나..)

19.10 이후부터는 그냥 설치가 되지만, 그 아래 판에서는 저장소 추가가 필요하다.

sudo add-apt-repository ppa:wireguard/wireguard
sudo apt-get update
sudo apt-get install wireguard

클라이언트 쪽에서 언급하겠지만, 클라이언트로 사용할 때에도 똑같은 절차를 밟아야 한다.

IP Forward 설정

/etc/sysctl.conf 에서 net.ipv4.ip_forward 을 활성화 해야 한다.

간단하게, 저 파일을 열고, 해당 부분을 찾은 뒤 주석(#)을 지운다. 재부팅하면 자동 적용된다.
당장 되게 하고 싶다면,

sudo sysctl -w net.ipv4.ip_forward=1

키 생성

Wireguard 의 설정 파일은/etc/wireguard 에 있다. 헌데, 여기는 일반인(?) 출입이 금지되어 있으므로, sudo -i 로 root 가 된 뒤에 아래 작업을 하는 게 편하다.

다음에 나열할 일련의 작업들은, 인터넷에서 공식처럼 떠도는데, 살짝 이해가 안될 수도 있다. 특히 tee 명령이 살짝 헷갈린다. 예전에 써놓은 글이 살짝 도움이 될 듯.

sudo -i
cd /etc/wireguard
umask 077  # 이건 꼭 안해도 되지만, 그래도 해주면 나중에 편하다.
wg genkey | tee privatekey | wg pubkey > publickey

맨 아랫줄이 핵심인데, 여러 명령을 한 줄에 써놔서 뭔가 암호처럼 보인다.
풀어보면 사실 별 게 아니다.

  • wg genkey : 공개키 암호화 시스템에서, 개인키(Private key)를 생성하라.
  • tee privatekey : wg genkey 는 생성된 키를 stdout(화면)으로만 출력하는데, tee 를 통해 먼저 privatekey 라는 파일로도 저장하라는 의미.
  • wg pubkey : tee 의 두번째 출력으로, wg genkey 의 결과를 wg pubkey 의 stdin 으로 보내라는 명령이 된다.
  • > publickey : wg pubkey 의 결과를 public key 라는 파일에 저장하라.

위 명령의 결과로, privatekey 와 publickey 라는 파일 2개가 만들어진다. 안에는 키들이 들어있는데, 공개키는 당연히 외부로 알려야만 하는 키지만, 개인키는 절대로 유출되면 안된다.

서버용 설정 파일 #1 : 기본 연결(오직 서버-클라이언트만 통신가능)

Wireguard 에는 wg 라는 실행파일과 wg-quick 이라는 스크립트가 제공된다. wg 는 Wireguard 의 ‘모든 것’이라 할 수 있고, wg-quick 은, 나같이 간단히 사용할 목적인 사람들을 위한 스크립트다.

man page 에는 이렇게 나와있다.

This is an extremely simple script for easily bringing up a WireGuard interface, suitable for a few common use cases.

따라서, wg-quick 을 이용한 방법만을 여기에 정리한다. (Korokithakis 에 따르면 wg 와 wg-quick 용 설정 파일은 서로 호환이 안된다고 한다.)

설정파일명은, 확장자만 conf 로 해주면 아무렇게나 정해도 된다. 다만, 보통 wg0.conf 로 하는 모양이다. 이 때 설정한 파일명은 가상 네트웍 기기명(wg0)으로 사용된다. 따라서 파일명은 이렇게 주기로 하고, 다음 내용을 입력한다.

[Interface]
Address = 내부 IP 주소. 원 주소와는 달라야 함. ex. 192.168.2.1
PrivateKey = 위에서 생성한 개인키. (private key) 파일 위치가 아니라, 키 자체(문자열)를 입력해야 한다.
ListenPort = 51820 (적절히 맘대로 바꿔도 된다.)
SaveConfig = false

[Peer]
# 이 서버에 접속할 클라이언트 등록.
# 랩탑 등 외부 기기용으로, 여러 개가 있을 때 각각 따로 따로 만들어줘야 한다. (키 공유가 될 지도?)
PublicKey = 외부 기기의 공개키 (문자열)
AllowedIPs = 192.168.2.2/32

[Interface] 항목에선, ‘현재 기기‘에 대한 설정을 해준다. 서버면 서버, 클라이언트면 클라이언트. 즉, 자신에 대한 설명이 여기에 들어간다.

Address 항목은, VPN 으로 할당할 LAN 주소를 입력해준다. 좀 더 정확하게 말하자면, wg0 으로 정의된 (가상) 네트웍 기기가 받을 IP 주소가 필요하다. 이 주소는 현재 사용하고 있는 LAN IP 주소와는 대역이 달라야 한다.
** IP/24 형식으로 넣어줘야 VPN 이 연결되었을 때도 호스트명을 사용할 수 있다. 이 기능을 사용하려면 클라이언트의 DNS 를 공유기 내부 IP 주소로 할당해줘야 한다.
적어도 Openwrt 의 경우, 여기를 192.168.2.1 또는 192.168.2.1/32 로 넣어주면, 호스트명을 사용할 수 없다.
자세한 내용은 간단판 참고.

PrivateKey 는 위에서 설명한 그대로. 파일 위치가 아니라, wg genkey 로 생성된 개인키를 그대로 입력해야 한다.

ListenPort 는 임의로 아무 번호나 주면 된다. 다른 영역과 겹치지 않도록 높은 숫자를 택하면 되고, Wireguard 서버가 공유기 뒤에 있을 경우, 이 포트를 공유기에서 열어줘야 한다. 여기서 포트는 UDP 다.

SaveConfig 항목이 조금 애매하다. 대부분, 여기를 True 로 설정을 하라고 한다.

True 로 되어 있다면, Wireguard 서비스가 끝날 때(간단하게, 서버가 종료될 때), wg0.conf 파일을, 현재 접속한 상황을 기준으로 새로 고침하여 저장한다.
아주 쉽게 확인할 수 있는 예로, [Peer] 항목에서 Endpoint = IP:Port 가 추가되어 conf 파일에 저장된다.

Endpoint 항목이 있으나 없으나 접속엔 전혀 차이가 없다. 혹시 같은 IP 에서 접속하면 좀 더 활성화(인증)가 빨라지려나?
아무튼, 뭐가 좋은진 모르겠다.

헌데, false 로 했을 때 이점은 확실히 있다. Peer 가 여러개라면, [Peer] 항목을 그 갯수만큼 만들어야 하는데, 이를 테면 아래와 같다. (wg-quick man page 에 있는 내용)

[Interface]
Address = 10.192.122.1/24
Address = 10.10.0.1/16
SaveConfig = true
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820

[Peer]
#Laptop
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
AllowedIPs = 10.192.122.3/32, 10.192.124.1/24

[Peer]
#Android Phone
PublicKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
AllowedIPs = 10.192.122.4/32, 192.168.0.0/16

[Peer]
#iPad
PublicKey = gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA=
AllowedIPs = 10.10.10.230/32

이 때, 각 [Peer] 에 설명을 주고 싶다면, #을 사용해서 주석을 넣어놓으면 된다.
헌데, SaveConfig 가 true 로 설정되어 있다면, 나중에 이 주석이 모두 사라져버린다.
따라서.. 그냥 false 로 해놓는 것도 나쁜 생각은 아닐 듯 하다.

이제 [Peer] 로 넘어간다.

여기는, 서버에 접속할 클라이언트들에 대해 기록해놔야 한다. Wireguard 는 공개키 암호화에 기반을 두고 있으므로, [Peer] 에서 가장 중요한 항목은 클라이언트의 PublicKey 항목이다.

PublicKey 에는, 클라이언트의 공개키를 입력한다. 서버에서와 마찬가지로 wg genkey 로 생성하면 된다.

PublicKey 는 전혀 어려울 게 없는데, 문제는 AllowedIPs 다. 여기가 좀 헷갈리고, 개념이 잘 잡히질 않는다. (네트웍에 대한 지식이 부족해서이리라.)

AllowedIPs 에는, 어쨌든 클라이언트의 IP 를 넣어준다. 방법은 아래와 같이 두가지다.

  1. 클라이언트가 자기 자신에게 부여한 VPN IP 주소. (/32 형식으로 넣어준다.)
  2. 서버와 클라이언트가 소속되어 있는 VPN IP 대역. (이 예에서는 192.168.2.0/24)

(단일) IP 로 설정

서버에는 192.168.2.1 을, 클라이언트에는 192.168.2.4 로 주소를 부여했다면, 여기엔 이렇게 넣어준다.

[Interface]
Address = 192.168.2.1
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820
SaveConfig = false

[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
AllowedIPs = 192.168.2.4/32

이제, 클라이언트가 자신을 192.168.2.4 로 IP 를 할당하고 서버에 접속하면 서로간 통신이 이뤄진다.

IP 대역으로 설정

** 다만, 이 방식은 Android, iOS 클라이언트에선 되는데, 우분투 클라이언트에선 되지 않았다. 우분투에선 반드시 IP 를 명시해줘야만 제대로 작동했다. (뭔가 설정이 더 필요할 듯 하다.)

[Interface]
Address = 192.168.2.1
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820
SaveConfig = false

[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
AllowedIPs = 192.168.2.0/24

IP 로 설정했을 때는 192.168.2.4/32 로 정확한 주소를 지정했지만, 이번엔 이 대역 전체를 지정했다. 이 두 방식 모두 문제는 없다.

AllowedIPs 설정은, ‘보낼 때는 라우팅 테이블 처럼, 받을 때는 ACL처럼’ 작동한다고 한다.

따라서, 저런 공개키를 가진, 192.168.2.0/24 대역의 어떤 클라이언트가 교섭을 시도해도 무조건 통과가 된다.
이렇다면, 같은 공개키 쌍을 여러 기기에서 공유하는 방법도 가능하다. 마치 ssh 처럼, 한 서버에 여러 클라이언트가 같은 계정(공개키쌍)으로 동시에 접속할 수도 있다.

워낙에는, [Peer] 항목을 위의 예처럼 여러 개를 만들어야 하는데, 같은 공개키쌍을 쓴다면, 굳이 그럴 필요가 없다. 이렇게 대역으로 해두면 여러개 만들 필요가 없어서 편리할 듯 하다.

예를 들자면, 위에선 Laptop, Android Phone, iPad 등으로 Peer 항목을 3개 만들었고, 각각 서로 다른 공개키 쌍을 사용했다. 물론, 저 클라이언트들은 각각 IP 대역이 다르기 때문에 따로 구분을 할 필요가 있었다.
그러나, ‘내’가 혼자서 여러 기기를 통해 Wireguard 서버에 접속한다고 했을 때, 굳이 공개키쌍을 여러개 만들고, Peer 설정도 그만큼 해줄 필요가 없다.
그냥 AllowedIPs 에 192.168.2.0/24 처럼 대역을 넣어주는게 간편하다.
다만, 이 방식은 내가 그냥 생각해냈기에, 보안에 문제가 있을 수도 있다.

AllowedIPs 에는 이처럼 단일 IP 를 넣어줄 수도, 대역을 넣어줄 수도 있다. 그러나, 이 설정과는 관계없이, 지금 상태로는 서버-클라이언트간 통신만 이뤄질 뿐, 서버의 LAN 으로는 접근이 불가능하다.
다시 말하자면, 클라이언트(192.168.2.4)에서 서버로 ping 192.168.2.1(서버) 은 가능하지만, ping 192.168.1.4(서버가 속한 LAN 의 다른 기기) 등은 작동하지 않는다.
엥? 이러면 무슨 의미가..? (여기까지는 그냥, ‘설정이 이렇다..’는 이론 설명이었다고 할 수 있겠다.)

이를 위해선 또 다른, 다소 복잡한 내용이 필요하다.

서버용 설정 파일 만들기 #2 : LAN 연결 가능하게끔.

#1 대로만 설정하면, 서로 ‘연결’만 됐다 뿐이지, 뭔가 작업은 할 수가 없다. 예를 들어, 서버가 속한 LAN 대역(192.168.1.0/24)에 접근이 불가능하다. ping 자체가 되지 않는다.

이를 위해서, 즉, 서버의 LAN 대역에 접근할 수 있게 하려면, IP Forward 기능을 실행시켜줘야 한다.
이 기능을 활성화 시키기 위해서는 먼저 서버의 네트웍 장치명을 정확히 알아야 한다.

# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:6a:df:ef brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.40/24 brd 192.168.1.255 scope global dynamic enp0s3
       valid_lft 601195sec preferred_lft 601195sec
    inet6 fe80::a00:27ff:fe6a:dfef/64 scope link 
       valid_lft forever preferred_lft forever
3: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none 
    inet 192.168.2.1/32 scope global wg0
       valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:71:7e:d7:36 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

위와 같은 네트웍 장치들이 있을 때, 이 중에서 실제 물리 장치, 다시 말해 LAN 을 담당하는 장치명을 알아내야 한다. 위의 경우 192.168.1.40 이 할당된 enp0s3 가 바로 ‘지금 필요한 장치’다.

참고로, wg0 은 Wireguard 가 사용 중인 장치, docker0 은 Docker 장치다.

따라서, 최종 명령은 이렇게 되고, wg0.conf 에 다음처럼 넣어준다.

[Interface]
Address = 192.168.2.1
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820
SaveConfig = false
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o enp0s3 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o enp0s3 -j MASQUERADE

[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
AllowedIPs = 192.168.2.4/32

명령의 정확한 의미는.. iptables 에 대해 공부가 필요하다. (지금 당장은 그냥 써먹기만 하련다.)

이제, 클라이언트에서 여기에 접속하면, 192.168.1.0/24 대역으로 접근이 가능하다. 예를 들어, 192.168.1.33 으로 ping 도, ssh 도 할 수 있게 된다.
그러나.. 그렇게 하려면 클라이언트의 설정에도 이 내용을 명시해야 한다.

아직까지 클라이언트에서 사용할 Wireguard 설정에 대해선 언급하지 않았는데, 미리 살짝 맛(?)을 보자면, 클라이언트에도 어느 대역에 접근을 할 지를 알려줘야 한다.

위의 경우, 클라이언트 입장에선 VPN IP 대역인 192.168.2.0/24 에 참여하려고 하고(192.168.2.x 로 ip 를 부여 받은 뒤), 그 이후 서버가 속한 LAN 대역인 192.168.1.0/24 에 접근하려고 할 예정이므로, 이 대역을 모두 ‘확실히’ 밝혀줘야 한다.

따라서, 클라이언트의 AllowdIPs 항목은 이렇게 된다.

AllowedIPs = 192.168.2.0/24, 192.168.1.0/24

이젠 완벽(?)하다. 클라이언트는 서버에 접속하여 서버가 속한 LAN 영역을 자유롭게 헤엄칠 수 있게 됐다.

그런데, 그렇다고 해도 하나, 마지막으로 해결해야할 문제가 있다. 이 방식으로 접근했을 때, 클라이언트는 자기 자신의 IP(공인) 를 그대로 유지한다. 즉, VPN 을 쓰는 목적 중, IP 를 바꿔치려는 의도가 꽤 될텐데, 이 방식으로 하면 그건 불가능하다.
이 숙제는 서버가 아니라 클라이언트의 몫이므로, 해법은 클라이언트 항목에서 설명하도록 하겠다.

Wireguard 실행/상시 실행 설정

드디어 실행!
wg 로도, wg-quick 으로도 실행이 가능하다고 하지만, 위 설정은 모두 wg-quick 을 대상으로 작성했으므로, 다음과 같이 실행한다.

# 시작
sudo wg-guick up wg0.conf

# 정지
sudo wg-guick down wg0.conf

이제 클라이언트에서 접근이 가능한 상태가 됐다.
그러나 서버를 껐다 다시 켜면 이 상태가 유지되진 않는다. 늘 작동하도록 만들려면 systemctl 로 등록시켜 줘야 한다.

그 전에, /etc/wireguard 에 좀 더 보안을 강화할 필요가 있다. (그렇다고 한다…)
이 글 그대로 따라했다면, 아래 내용은 안해도 되긴 하지만. 확인도 할 겸, 명령을 옮겨 본다.

sudo chown -R root:root /etc/wireguard/
sudo chmod -R og-rwx /etc/wireguard/*

이제 systemd 로 서버 시작시에 자동 실행되도록 등록시킨다.

sudo systemctl enable wg-quick@wg0.service

wg0.service 는, /etc/wireguard/wg0.conf 라는 파일이 있다는 가정하에 나왔고, 파일명이 다르다면 그 이름을 사용해야 한다.

systemd 를 사용하여 시작/중지하려면:

sudo systemctl start wg-quick@wg0.service
sudo systemctl stop wg-quick@wg0.service

끝! 서버에선 더 볼 일이 없다.

1.2 Openwrt 에서.

따로 작성했음.

2. 클라이언트 설치

2.1 우분투 계열

설치 및 설정

우분투 계열은 서버 설치 때와 똑같이 하면 된다. 19.10 이상이면 그냥 설치 가능, 그 아래 판이라면 PPA 추가가 필요하다.
설치가 끝나면, 역시 /etc/wireguard 로 이동하여 설정 파일을 만들어야 한다.

방식은 서버 때와 다를게 없다.
단순 접속은 별 의미가 없으므로, 서버 LAN 영역에까지 접근할 수 있도록 설정하려면, 아래와 같은 식으로 해야 한다. 물론, 공개키쌍은 이미 생성해놔야 한다.

/etc/wireguard/wg0.conf (또는 다른 이름)으로 설정 파일을 생성하고, 다음을 입력한다.

[Interface]
Address = 192.168.2.5 (서버와 같은 대역으로, 맘대로 정한다.)
PrivateKey = <이 클라이언트의 개인키>
SaveConfig = false (True 를 원하면 True 로.)

[Peer]
PublicKey = <서버의 공개키>
AllowedIPs = 192.168.2.0/24, 192.168.1.0/24
Endpoint = <서버 주소>:서버 포트(서버 설정에서 ListenPort 로 설정한)

[Interface] 항목은 서버 때와 똑같다. 나 자신에 대한 정보를 넣는다. Address 에 들어갈 주소는 다른 기기와 충돌되지 않도록 적절히 선택해야 한다. (당연한 얘기지만,) 서버에서 설정한 IP 대역에서 결정해야만 한다.

PrivateKey 에는, 이 기기(클라이언트)를 위해 생성한 키 쌍에서 Private Key 를 넣는다. 서버의 Private Key 가 아니다.

SaveConfig 는 서버 때와 같다.

[Peer] 항목은 대부분 서버 때 다 설명을 했다.

PublicKey 에는 서버의 공개키를 넣고, AllowedIPs 에는 VPN 으로 구성된 IP 대역과, 서버의 LAN 대역 주소를 넣어준다.

가장 중요한 항목은 Endpoint 이다. 여기엔 서버의 IP주소와 포트번호를 넣어준다. 서버가 공유기 뒤에 있는 경우, 공유기에서 이 포트를 서버로 넘겨(Port Forward)줘야 한다.

실행

역시 서버 때와 같다.

# 실행
sudo wg-quick up wg0
# 중지
sudo wg-quick down wg0

클라이언트는 굳이 자동 실행할 필요가 없으므로 그냥 저렇게만 해주면 되겠다.
접속하고, ping 192.168.2.1 등으로, 제대로 작동하는지 확인해본다.

2.2 Android/iOS 계열

설치

Google Play, App Store 에서 Wireguard 를 검색하고 설치한다.
여기도 마찬가지로 공개키쌍이 필요한데, 이 키쌍은 PC 에서 만들고 그걸 그대로 사용한다. Android/iOS 용 Wireguard 도구에서 키 쌍을 만들 수는 있지만, 공개키를 다시 서버에 옮겨적어야 하는 문제가 있으니, 그냥 PC 에서 만드는 편이 낫다.

** 휴대기기에서 만든 키를 서버로 옮기는 게 생각보다 쉽지 않다. 안드로이드라면 PC와 직접 연결한 뒤 파일로 받는 방법도 있겠으나, 역시 불편하다. 네트웍으로 어딘가 올렸다가 받는 방법(이메일이라든가, 클라우드라든가)은 보안에 문제가 있을 수 있다.

자, 다시 한번 공개키 쌍을 만든다. 위에서 만든 우분투용 공개키쌍을 그대로 재활용해도 될 듯은 한데.. 이 부분이 좀 애매하기에 그냥 새로 만들기로 한다.

설정파일은 우분투 때와 똑같다.
적당한 이름을 주고(예를 들어, forAndroid) 다음 내용처럼 텍스트 파일을 만든다.

[Interface]
Address = 192.168.2.6 (서버와 같은 대역으로, 맘대로 정한다.)
PrivateKey = <이 클라이언트의 개인키>
SaveConfig = false (True 를 원하면 True 로.)

[Peer]
PublicKey = <서버의 공개키>
AllowedIPs = 192.168.2.0/24, 192.168.1.0/24
Endpoint = <서버 주소>:서버 포트(서버 설정에서 ListenPort 로 설정한)

이제 이 파일을 스마트기기의 Wireguard 로 넘겨줘야 한다. 기기의 Wireguard 는 다음과 같이 세가지 방식으로 설정파일을 만들 수 있다.

  • Create from file or archive
  • Create from QR code
  • Create from scratch

첫번째는 위에서 만든 설정파일을 기기로 옮겨야 하는 수고가 뒤따른다. 따라서 탈락. 마지막 방법은 이상요상한 문자의 나열인 공개키/개인키를 직접 손으로 넣어줘야만 한다. 역시 탈락.

그리하여 채택한 두번째 방법. 바로, QR Code 를 사용한 방식이다.
이를 위해선 프로그램(qrencode) 설치가 필요하다. 물론, PC, 우분투에서.

sudo apt install qrencode

위 설정파일을 forAndroid 라고 저장했다면, 이 파일을 QR 코드로 바꿔주는 명령은 다음과 같다.

qrencode -t utf8 < forAndroid

이제, (신기하게도) 터미널 화면에 대문짝만하게 QR 코드가 뜬다.
또는, 별 필요는 없지만, 굳이 그래픽파일로 만들고 싶다면,

qrencode -t png < forAndroid -o wg-config

어떤 방식으로든 만들어진 QR 코드를, 기기의 Wireguard 에서 읽으면 설정이 자동으로 완성된다.

** 만약 Android 클라이언트에서 VPN 내부로는 접속이 되지만, 외부(구글, 네이버 등)로 신호가 나가지 않는다면, Android Wireguard 에서, DNS Servers 항목에 적절한 DNS 서버 주소를 넣어준다. (8.8.8.8 등)
iOS 에서는 이 항목을 넣지 않아도 잘 됐다. Android 프로그램 쪽에 뭔가 문제 오류가 있는 모양이다.

접속하고, 확인해본다.

2.3 클라이언트 IP? 서버 IP? 공인 IP 바꿔치기(?) 해결법

VPN 을 사용하는 목적이 서버와 서버의 LAN 영역에 접근하려는 목적이라면, 위 설정으로 충분하다.
그러나 만약, 서버의 공인 IP 를 클라이언트가 획득(?)하려는 목적이라면, 위 방식으로는 부족하다.

예를 들어, 위 방식으로 접근한 후 공인 IP 를 확인해보면(ipchicken.com 등) 클라이언트가 받은 공인 IP 가 그대로 나타남을 확인할 수 있다.

자.. 클라이언트 IP 를 서버 IP 로 위장(?)하려면?
마지막 설정이 필요하다. 서버에는 건드릴게 없고, 클라이언트만 살짝 바꿔주면 된다. 그것도 딱 한 줄.

[Interface]
Address = 192.168.2.6 (서버와 같은 대역으로, 맘대로 정한다.)
PrivateKey = <이 클라이언트의 개인키>
SaveConfig = false (True 를 원하면 True 로.)

[Peer]
PublicKey = <서버의 공개키>
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = <서버 주소>:서버 포트(서버 설정에서 ListenPort 로 설정한)

위에서 만든 설정과 동일하지만, AllowedIPs 항목만 바뀌었다. 이 값은 고정값으로, 그냥 저렇게 넣어주면 된다.

0.0.0.0/0, ::/0 의 의미이렇다는데.. 알랑말랑? 아무튼 저렇게 쓰라고 하니 쓰면 되겠지.
여기서, 0.0.0.0/0 는 IP4, ::/0 은 IP6 다. IP6 를 쓰지 않는다면 0.0.0.0/0 만 있어도 된다.

이걸로 대망의 Wireguard 설치/설정은 끝.

2.3 Openwrt 에서 Hostnames 사용 시

공유기에 Hostname 을 설정해서 사용할 경우, Wireguard 로 연결하면 이 기능이 작동하지 않는다. 이를 위해선 DNS 를 공유기 LAN IP 로 설정해줘야 한다.

[Interface]
Address = 192.168.2.7 (서버와 같은 대역으로, 맘대로 정한다.)
PrivateKey = <이 클라이언트의 개인키>
SaveConfig = false (True 를 원하면 True 로.)
DNS = 192.168.1.1 (공유기 랜 IP)

[Peer]
PublicKey = <서버의 공개키>
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = <서버 주소>:서버 포트(서버 설정에서 ListenPort 로 설정한)

DNS 설정이 되어 있지 않으면 Hostname 으로 접근이 불가능하다. 물론, 그냥 IP 로는 된다. 또, 상황에 따라 다른 듯은 한데, DNS 를 아예 설정하지 않으면, 외부 접속(네이버, 구글 등등)이 아예 되지 않는 경우도 있다. 8.8.8.8 등, 적절한 DNS 가 필요하다.

따라서, 그냥 공유기 IP 를 넣어주는게 속 편하겠다.

안녕하세요. 글 남겨주셔서 고맙습니다.