Openwrt : Wireguard 설치/설정.

꽃삽질이 되고 말았으나.. 그래도 해결은 했다. 딱 하나 빼고는.
그 딱 하나는 바로, VPN 연결 뒤 공유기에 정의된 호스트명으로 접근이 될 지 여부다. (이 얘긴 뒤에 다시.)

가능한한 Luci 로 설정하고, 때에 따라선 CLI 로 직접 수정한다. uci 도구는 아직 사용법에 익숙지 않아서, 여기선 전혀 언급하지 않는다.


꾸러미 설치

Luci 용까지 해서 총 3개를 설치한다.

opkg update
opkg install wireguard luci-proto-wireguard luci-app-wireguard

키 쌍 생성

공개키 쌍을 생성해야 하는데, 방법은 우분투 때와 같다.
다만, /etc/wireguard 디렉토리는 자동 생성되지 않는데, 꼭 여기다 넣어야 할 이유는 없지만, 그냥 다들 그리 하는 듯 하므로.. ‘보관’한다는 생각으로 여기에 넣어 놓는게 좋겠다.

mkdir -p /etc/wireguard
chmod 700 /etc/wireguard
cd /etc/wireguard
wg genkey | tee ./privatekey | wg pubkey > ./publickey

인터페이스 설정

Luci

Luci – Network – Interfaces 로 이동하여, Add New interface 를 실행한다.

이름은 보통 ‘wg0’ 등으로 주는 모양이니 그렇게 하도록 하고, Protocol 을 Wireguard VPN 으로 선택한다.

세부 설정은 다음과 같다.

General Setings(서버 역할)

  • Private Key : 위에서 생성한 Private Key
  • Listen Port : Private Port 영역(49152 ~ 65535)에서 적당하게 선택한다.
  • IP Addresses : 공유기가 속한 LAN IP 대역이 아닌, 클라이언트가 속한 대역도 아닌 새 대역의 IP 로 설정한다. IP/24 형식으로 넣어야 hostname사용할 수 있다. (ex. 10.3.3.1/24 등등)

Advanced Settings, Firewall Settings 는 지금 당장은 건드릴게 없다.

CLI

/etc/config/network 에 다음 내용을 추가한다.

config interface 'wg0'
	option proto 'wireguard'
	list addresses '10.3.3.1/24'
	option private_key '어쩌구 저쩌구..='
	option listen_port '51820' # 또는 적절히 선택.

config interface 뒤의 이름(wg0)은 달리 정해줘도 된다. 그러나, wg0 으로 쓰는게 많이 쓰이는 명명법이다.

Peers(서버에 접속 가능한 클라이언트 목록)

이전 글을 참고하여 클라이언트의 공개키, IP 등등을 넣어준다.

Luci 로는, Luci – Network – Interfaces – wg0 – Peers 로 이동하여 항목을 입력한다.

  • Description : 적당한 이름.
  • Public Key : wg genkey 로 클라이언트를 위해 생성한 공개키.
  • Allowed IPs : 서버에서 설정한 동일한 IP 대역의 다른 주소. (ex. 10.3.3.10 또는 10.3.3.10/32 등) 다만, 여기서는 10.3.3.10/24 는 안되고, 10.3.3.0/24 는 가능하다. (뒤에서 다시 정리)
  • Route Allowed IPs : 선택
  • Endpoint Host : 넣으나 안넣으나 큰 관계없다. 넣으려면, 서버의 주소(공인 IP)를 넣어준다.
  • Endpoint Port : Private Port 구간(49152 ~ 65535)에서 적절히 선택.
  • Persistent Keep Alive : 25 로 하라고 하는데..

CLI 로는, 다음과 같이 할 수 있다.

config wireguard_wg0 'wgclient_1'
	option route_allowed_ips '1'
	option public_key '어쩌고 저쩌고'
	option description '클라이언트#1'
	option persistent_keepalive '25'
	list allowed_ips '10.3.3.0/24'

** Allowed IPs: 단독 주소, 또는 대역 선택?

** 대역이 되긴 됐는데, 또 안될 때도 있다. 그냥, 기기당 하나씩 키쌍을 생성해서 따로 따로 설정을 해주는게 속편한 방법이라고 생각한다.

아래 글은 그냥 참고..


Allowed IPs 에는 구간(10.3.3.0/24 등)을 넣어도 되고, 단독 주소(10.3.3.10/32)를 넣어도 된다. 그런데, 여기에 10.3.3.3/24 를 넣으면 뭔가 오작동을 하기도 한다. (내 실수인지는 모르겠으나..)

‘대역도 가능하다’의 의미는, 공개키쌍을 하나만 만들고, 여러 기기에서 나눠쓸 수 있다는 뜻이 된다.
예를 들어, 같은 공개키 쌍을 전화기에, 랩탑에, 태블릿에 설치해놓고, 각각 IP를 달리 준 뒤 동시에 접속해도 사용이 가능하다.

  • 서버(Openwrt – wg0)의 Allowed IPs : 10.3.3.0/24
  • 전화기 : 10.3.3.2
  • 랩탑 : 10.3.3.3
  • 태블릿 : 10.3.3.4

이러면, 같은 공개키쌍으로 이용할 수 있다. 이 방법이 싫으면, Peer 설정을 그 수만큼 해줘어야만 한다. 즉, 공개키 쌍도 같은 수만큼 만들어야 한다.

** 대역을 선택했다면, Peer 를 추가할 때는 반드시 단독 IP 로.

예를 들어, Peer 가 하나라면 그냥 위와 같이 Allowed IPs 에서 구간을 넣어줘도 된다.
그러나, Peer 가 2개 이상일 때, 두 Peer 에 모두 같은 대역을 넣어주면, Openwrt Router가 패닉에 빠져버린다.

config wireguard_wg0 'wgclient_1'
	option route_allowed_ips '1'
	option public_key '어쩌고 저쩌고'
	option description '클라이언트#1'
	option persistent_keepalive '25'
	list allowed_ips '10.3.3.0/24'

config wireguard_wg0 'wgclient_2'
	option public_key '우짜고 저짜고'
	option description '클라이언트#2'
	list allowed_ips '10.3.3.0/24'
	option route_allowed_ips '1'

이처럼 Peer 가 2개 이상일 때, 두 개 설정에서 Allowed IPs 가 ‘10.0.0.0/24‘ 등으로 동일하게 설정되어 있다면, 공유기가 뭔가 이상한 상태에 빠진다. 다운되지는 않지만, ping 에도 반응하지 않고, ssh 접속, Luci 접속 모두 불가능해진다.

만약 Extroot 를 사용 중이라면 설정이 외부 매체에 저장되므로 공유기를 끄고, 이 매체를 빼서 다른 기기에 연결한 뒤 config/network 파일을 수정하면 되지만, 그렇지 않을 경우는 초기화하는 방법 밖에 없지 않을까. 재수없으면 아예 펌웨어를 다시 심어야할 지도.

내 기기(Gl-iNet BL1300)에서만 이런 현상이 생기는 지는 모르겠지만, 아무튼 이런 상황이 벌어진다.
따라서, Peer 가 2개 이상이고, 한 쪽에서 구간 설정을 해줬다면, 다른 쪽(들)은 단일 IP 로 지정을 해줘야만 한다.

config wireguard_wg0 'wgclient_1'
	option route_allowed_ips '1'
	option public_key '어쩌고 저쩌고'
	option description '클라이언트#1'
	option persistent_keepalive '25'
	list allowed_ips '10.3.3.0/24'

config wireguard_wg0 'wgclient_2'
	option public_key '우짜고 저짜고'
	option description '클라이언트#2'
	list allowed_ips '10.3.3.3'
	option route_allowed_ips '1'

** 대역에 관한 쓸데없는 얘기는 여기까지.


Interfaces 설정은 끝났다. 클라이언트(다른 기기) 설정은 이 글 맨 마지막에.
이제 Firewall 차례다.

Firewall 설정

포트 열기

Luci – Network – Firewall 로 이동하여, Traffice Rules 탭에서 Add 를 실행한다.

위에서 ‘포트’를 설정했으므로, 그 포트를 열어줘야 한다.

Add 후에 이름은 ‘AllowWireguard’ 등으로 적당히 준 뒤, 다음 항목을 설정한다.

  • Protocal : TCP UDP
  • Source zone : WAN 및 WAN6
  • Destination zone : Device (input)
  • Destination port : 위에서 선택한 포트 번호
  • Action : accept

Zones 설정

Luci – Network – Firewall 로 이동하여, General Settings 탭에서 Add 를 실행한다.

  • Name : wireguard 등으로 적당히.
  • Input/Output/Forward : 모두 accept
  • Masquerading : 선택
  • MSS clamping : 선택
  • Covered Networks : 위에서 만든 wg0

그리고 이제 Zone 간 포워딩 규칙을 설정해줘야 한다.

  • Allow forward to destination zones: lan, wan
  • Allow forward from source zones: lan

서버 설정은 끝. Save & Apply 로 설정을 적용한다.

클라이언트 설정

클라이언트 설정을 하기 위해선, 먼저 서버에서 Peer 설정을 해야 한다.
물론 나중에 해도 되긴 하지만.. 아무튼, 상호에서 서로를 인식할 수 있게끔 해줘야 하는데, 어렵게 얘기하자면, 서로 발행한 공개키를 양쪽 모두에 등록해야만 한다.

쓸데없는 얘기 먼저.

그/런/데!
Luci – Status – Wireguard Status 를 보면, QR-Code 를 보여주는 항목이 있다.

작은 글씨로 써 있는 내용을 우리말로 옮겨보자면, wg 인터페이스(즉 서버설정)에 따라 작성되고, Peer(클라이언트) 용으로 Private/Public 키를 매번(페이지 새로고침) 생성하여, 그 결과를 QR 코드로 보여준다고 한다.

정리하면 이렇다. Wireguard config 파일 형식에 따라,

  • Interface 항목 : Private/Public 키를 새로 생성하여, Private 키를 QR에 첨부.
  • Peer 항목 : 서버의 Publickey 를 첨부. Allowed IPs 로 0.0.0.0/0 추가.

이런 정보를 QR 로 만들어준다. 이걸 스마트기기에서 읽어오면, 해당 정보가 자동 입력이 되는데..

여기에 큰 문제가 하나 있다.

Wireguard 는 Peer to Peer 통신이 기본이므로, 상호 공개키를 서로 등록시켜줘야만 한다. 위 방법은, 클라이언트는 서버의 공개키를 알고 있지만, 서버는 클라이언트의 공개키를 알지 못하는 상황이 된다.

서버에 클라이언트의 공개키를 등록시켜주려면, 위에서 언급했듯, /etc/config/network 에 공개키가 저장되어야만 한다.

config wireguard_wg0 'wgclient_1'
	option route_allowed_ips '1'
	option public_key '어쩌고 저쩌고'
	option description '클라이언트#1'
	option persistent_keepalive '25'
	list allowed_ips '10.3.3.0/24'

‘어쩌고 저쩌고’가 바로 그 공개키인데, 이 공개키는 Luci 의 Show/Hide QR-Code 항목만으로는 생성되기만 할 뿐, 등록되지는 않는다.

이 공개키를 등록하려면, 스마트기기에서 QR 코드를 읽어온 후, 거기에 나타난 공개키를 눈으로 보고, 손으로 서버에 추가해주거나, 아니면 그 공개키를 어떤 식으로든 서버로 옮겨서 넣어주는 방법밖에 없다.

하여… 이 방식은 결코 좋은 방식이라고 할 수 없다.
Gl-iNet BL1300 공식 펌웨어(Openwrt 이전 판 기반)에서는 이 기능을 좀 더 지능화시켜서, 서버에서 Peer 추가, 그에 따른 QR 코드 생성이 연동되어 작동하게끔 설계했다.

아무튼간에, Luci 에서 보이는 QR 코드는 별로 쓸 데가 없다.
그냥 수동으로 만드는 편이 낫다.

진짜 설정

클라이언트를 위한 공개키/개인키는 미리 만든다.

wg genkey | tee privatekey | wg pubkey > publickey

위 키 중 공개키는 서버의 Peers 항목에 등록시켜준다.
나머지 개인키로 설정 파일을 만든다. 스마트 기기에 등록한다는 전제하에 파일명은 아무거나(config-openwrt 라 가정). 그리고 이런 식으로 설정한다.

[Interface]
Address = (서버와 같은 대역으로, 맘대로 정한다.) (ex. 10.3.3.5/3)
PrivateKey = <이 클라이언트의 개인키>
DNS = <서버의 LAN IP> (ex. 192.168.1.1)

[Peer]
PublicKey = <서버의 공개키>
AllowedIPs = <VPN ID 대역>, <서버 LAN IP 대역> (ex. 10.3.3.0/24, 192.168.1.0/24)
Endpoint = <서버 주소>:서버 포트(서버 설정에서 ListenPort 로 설정한)

[Peer] 의 AllowedIPs 는 다음과 같이 두가지 방식 중 하나를 택할 수 있다.

  • <서버 LAN IP 대역> (ex. 10.3.3.0/24, 192.168.1.0/24)
  • 0.0.0.0/0

상위 설정을 따르면, VPN 연결한 후 기기의 공인 IP 가 원래 자신의 공인 IP 그대로로 고정되며, 하위 설정, 즉 0.0.0.0/0 을 택하면 서버의 공인 IP 설정을 따라간다.
필요에 따라 적절히 선택해주면 된다.

[Interface] 에서 DNS 항목은 넣어줄 수도 안해줄 수도 있지만, Openwrt 공유기의 Hostnames 를 사용하려면, 반드시 공유기 LAN 주소를 DNS 로 넣어줘야 한다.

이제 다 만들어진 텍스트 파일을, QR 코드로 변환한다.

qrencode -t utf8 < config-openwrt

그러면 QR 코드가 터미널 상에 보이는데, 이걸 스마트기기에서 인식시키면 된다.

끝!!

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