우분투 서버로 네트워크 전체에 VPN 연결 구축하기

!
경고: 이 글이 작성된 지 365일이 넘었습니다. 글의 정보가 오래되어 부정확할 수 있습니다.

중국에서 외국인으로 살다 보면, YouTube와 Netflix를 보려고 VPN 어플로 전환하는 과정이 진짜 귀찮아집니다.

더 이상 VPN 어플을 사용하지 않도록 이번 글에서는 네트워크 전체에 VPN 연결을 구축해보겠습니다!

준비물

준비물은 다음과 같습니다:

  • OpenVPN 설정을 제공하는 VPN 업체. 다른 프로토콜도 아마 작동하겠지만, 이 글에선 다루지 않습니다.
  • 우분투 서버가 깔려있는 서버나 가상머신. 최신 버전을 사용하는 것을 추천합니다. 이 글은 16.04 LTS 버전을 기준으로 작성되었습니다.
  • 리눅스와 네트워킹 지식
  • (필수는 아니지만 추천) DHCP 서버의 기본 게이트웨이 설정을 변경할 수 있는 라우터

리눅스와 네트워킹 지식이 없다면 나중에 인터넷 연결이 작동하지 않을 수도 있습니다! 이 글을 따라하기 전에 관련 정보를 검색하고 진행하세요.

준비물 중, DHCP 서버의 기본 게이트웨이 설정을 변경할 수 있는 라우터가 중요합니다. 라우터가 이 설정을 지원하지 않는다면 모든 기기에 네트워크 설정을 변경하여 새 리눅스 서버로 네트워크 트래픽을 우회시켜야 합니다. 차라리 그냥 각 기기마다 VPN 어플을 설치하는게 더 쉽겠지만, 이 글은 VPN을 지원하지 않는 기기에게도 매우 유용하기 때문에 한번 시도해보시는 걸 추천합니다.

주말에 한번 취미삼아 구축하던, 진짜 필요해서 구축하던, VPN 서버는 정말 유용하게 써먹습니다. 단 구축후 생길 문제에 대비해 어떻게 다시 네트워크를 초기화하는지 알고 넘어가시면 좋습니다.

VPN 설정

OpenVPN 파일을 VPN 제공업체에서 다운받습니다. 다운로드 페이지에 만약 아이디와 비밀번호가 나열되어 있는 경우 옆에 적어둡니다.

(만약 아이디와 비밀번호가 별도로 나와있지 않으면, VPN 제공업체에 로그인하는 계정의 아이디와 비밀번호일 수도 있습니다. 나중에 실헝해보고 변경하세요.)

VPN 제공업체에 따라서 한 통합 OpenVPN 파일을 제공할 수도 있고, 아니면 여러개로 나뉘어진 설정 파일들을 제공할 수도 있습니다. 나중에 키 설정하고 잡다한 설정을 건드리지 않아도 되기에 되도록이면 통합되어 있는 파일을 받는 것이 좋습니다.

이제 VM이나 서버로 이동해서 다음 명령을 실행합니다:

ifconfig

현재 네트워크 설정이 다음과 같이 나타납니다. 왼쪽에 있는 네트워크 인터페이스 이름을 적어둡니다.

enp2s0    Link encap:Ethernet  HWaddr <숨김>  
            inet addr:192.168.0.100  Bcast:192.168.0.255  Mask:255.255.255.0
            <생략>
            
lo        Link encap:Local Loopback  
            inet addr:127.0.0.1  Mask:255.0.0.0
            <생략>

예시의 네트워크 인터페이스 이름은 enp2s0이고, IP 주소는 192.168.0.100으로 표시되는데, 나중에 사용하기 위해 일단 메모해둡니다.

OpenVPN을 설치합니다:

sudo apt install openvpn

설치가 완료되면 설정을 시작합니다. 주어진 통합 설정 파일을 복사합니다:

sudo cp <VPN 이름>.ovpn /etc/openvpn/<VPN 이름>.conf

만약 여러개로 나뉘어진 설정 파일들을 .ovpn 파일과 함께 받았을 경우, 키 파일을 확인합니다. 이름이 ca.rsa.2048.crt나 비슷하면 필요한 키 파일이 맞습니다. (2048은 keysize로, VPN 제공업체마다 다를 수 있습니다.) 키 파일을 찾은 후 복사합니다:

sudo cp ca.rsa.2048.crt crl.rsa.2048.pem /etc/openvpn

만약 통합 OpenVPN 파일을 받았다면 이 과정을 건너뛰어도 됩니다.

여기에서 왜 .ovpn 파일을 .conf로 확장자를 변경했냐면, 이렇게 수정해야 systemd로 OpenVPN을 제어할 수 있기 때문입니다. 이 변경으로 설정 파일이 systemctl에 등록되고, 실행할 때 OpenVPN@VPN-이름으로 활성화할 수 있습니다.

다음으로, VPN 아이디와 비밀번호를 /etc/openvpn/login에 적습니다:

아이디-여기
비밀번호-여기

예를 들어, 이렇게 적으면 됩니다:

ericswpark
examplepassword12345

저장하고 나간 다음, /etc/openvpn/<VPN 이름>.conf을 열고 다음 줄을 편집합니다:

auth-user-pass

이렇게 변경합니다:

auth-user-pass /etc/openvpn/login

아까 만약 키 파일이 분리되어 있는 파일을 받으셨다면 다음 줄들도 수정해야 합니다:

ca ca.rsa.2048.crt
crl-verif crl.rsa.2048.pem

이렇게 변경하세요:

ca /etc/openvpn/ca.rsa.2048.crt
crl-verif crl.rsa.2048.pem

그럼 VPN 설정이 완료되었습니다!

저장하시기 전에, 추가적으로 몇가지 유용한 설정들이 있습니다. 예를 들어, 인터넷 연결이 불안정한 곳이라면 persist-tun을 비활성화하는 것이 좋습니다. 이 설정을 비활성화한다면 VPN이 재시작시 터널 인터페이스를 삭제하고 원래 인터넷 연결로 VPN 서버를 검색합니다. 이게 왜 유용하냐면 터널 인터페이스가 죽어있다면 이 인터페이스로 VPN 서버를 검색할 수 없기 때문입니다.

다음 줄을 찾고:

persist-tun

줄 앞에 #을 적어 비활성화시킵니다:

# persist-tun

만약 서버가 연결을 활성 상태로 유지하게 만들고 싶다면 다음 줄들을 찾거나 추가합니다:

keepalive 10 30
resolv-retry infinite

마지막 줄은 기본 설정이 어쩌피 무한이기 때문에, 꼭 필요하지는 않습니다. 첫 번째 줄은 OpenVPN 클라이언트에게 VPN 서버를 10초마다 핑(--ping)하게 만들고, 만약 응답이 없을 경우 30초마다 재시작(--ping-restart)을 하게 만듭니다. 중국에선 황금방패 (Great Firewall of China)가 TCP RST 패킷을 수시로 보내거나 조용히 연결을 죽이기 때문에 이 설정이 매우 유용합니다. 설정값을 조절하면서 연결이 안정적이도록 수정할 수 있지만, 제 경험으로 30초 정도면 VPN 서버에 적당한 부하를 걸면서 충분히 안정적인 연결을 유지할 수 있습니다.

저장하고 VPN 서버를 테스트합니다. 중국에선 그냥 구글을 핑하면 확인할 수 있지만, 만약 이 튜토리얼을 중국이 아닌 다른 나라에서 진행한다면 ifconfig을 다시 확인해도 됩니다.

클라이언트를 실행시킵니다:

sudo openvpn --config /etc/openvpn/<VPN 이름>.conf

로그에서 Initialization Sequence Completed라는 문구가 나온다면 VPN이 정상적으로 동작한다는 것입니다. Ctrl-C를 눌러 VPN 터널을 죽이고 다음으로 넘어갑니다.

수동 IP 설정하기 (필수는 아니지만 추천)

이제 VM이너 서버에 수동 IP를 설정하는 것을 추천합니다. 나중에 기본 게이트웨이 설정에서 IP가 변경되면 일이 매우 귀찮아지기 때문입니다.

라우터 관리 페이지에 접속합니다. 가정 라우터는 거의 대부분 라우터 밑 스티커에 정보가 인쇄되어 있습니다. 만약 스티커를 때어버렸다면 (…), 구글에서 라우터 제조사를 검색한 다음 관리 IP 주소를 찾으면 됩니다. 그마저도 없다면 대부분의 라우터는 기본 게이트웨이가 관리 페이지입니다. 그것도 안 된다면 수동으로 IP 주소를 하나하나 확인합니다: 192.168.0.1, 192.168.1.1, …

이 라우터 IP를 적어둡니다. 관리 페이지에 접속한 후 DHCP 주소 할당이나 비슷한 메뉴로 들어갑니다. (국내 라우터는 대부분 수동 IP 할당 이렇게 메뉴가 있습니다.) 아까 맨 앞에 MAC 주소를 기억한다면 이제 여기에 입력을 하면 됩니다. (안 적어 두었다면 다시 VM이나 서버에서 ifconfig를 확인합니다.)

주소를 적은 다음에 적용합니다. 이제 VM이나 서버에다가 설정을 더 추가해야 합니다. /etc/network/interfaces 에서 다음 줄들을 찾습니다:

auto enp2s0
iface enp2s0 inet dhcp

인터페이스 이름에 차이가 있을 수 있습니다. 다음과 같이 수정하세요 (인터페이스 이름은 원래 있던 그대로 두어야 합니다):

auto enp2s0
iface enp2s0 inet static
    address 192.168.0.100
    netmask 255.255.255.0
    gateway 192.168.0.1
    dns-nameservers 1.1.1.1 1.0.0.1

DNS 서버는 아무거나 괜찮은데, 전 여기에서 CloudFlare의 1.1.1.1로 설정했습니다. 여기에서 올바른 IP 주소와 넷마스크를 입력했는지 확인하세요! IP 주소는 아까 라우터 관리자 페이지에서 적어두었던 수동 IP 주소를 입력하면 되고, 넷마스크와 기본 게이트웨이는 현재 인터넷 설정에서 찾으면 됩니다 (거의 대부분 라우터의 IP입니다.)

기본 게이트웨이 설정이 중요한데, 설정 없이 나중에 라우터 설정에서 DHCP 서버 설정을 변경해 VM/서버의 IP 주소를 뿌리게 된다면 VM/서버에서 자기 자신으로 기본 게이트웨이가 설정됩니다. 그래서 기본 게이트웨이가 현재 설정되어 있는 게이트웨이와 같은지 확인하는 것이 중요합니다.

설정이 완료되면 라우터와 VM/서버를 차례대로 재부팅 후, 인터넷이 동작하는지 확인합니다.

터널 설정하기

일단 OpenVPN 서비스를 부팅 시 실행되도록 활성화시킵니다:

sudo systemctl enable OpenVPN@<VPN name here>

이 명령을 실행할 때 .conf 확장자를 적으면 안 됩니다!

다음으로 IPv4 포워딩을 설정해야 됩니다. /etc/sysctl.conf을 연 다음 다음 줄을 찾아서:

# net.ipv4.ip_forward = 1

다음과 같이 변경합니다:

net.ipv4.ip_forward = 1

#을 제거하고, 저장후 넘어갑니다.

sysctl에 새 설정을 적용시킵니다:

sudo sysctl -p

이제 방화벽과 라우팅을 설정하도록 하겠습니다.

iptables

라우팅 테이블 설정이 이 튜토리얼에서 가장 어렵습니다. 저도 그렇게 이해가 완전히 되진 않지만 한번 설명해보겠습니다.

일단 루프백 (loopback) 인터페이스를 사용한 루프백 트래픽을 허용해야 합니다. 다음 명령을 실행합니다:

sudo iptables -A INPUT -i lo -m comment --comment "loopback-input" -j ACCEPT
sudo iptables -A OUTPUT -o lo -m comment --comment "loopback-output" -j ACCEPT

다음으로 네트워크에 들어오는 트래픽과 터널 인터페이스로 나가는 트래픽을 허용해야 합니다. (인터페이스 이름을 잊어버렸다면, 다시 VPN 연결을 위에 있는 명령으로 활성화시킨 다음, ifconfig으로 인터페이스 이름을 확인하면 됩니다.) 인터페이스 이름을 바꾼 다음 명령들을 실행합니다:

sudo iptables -I INPUT -i enp2s0 -m comment --comment "Local network" -j ACCEPT
sudo iptables -I OUTPUT -o tun0 -m comment --comment "VPN network" -j ACCEPT

이제 OpenVPN의 트래픽을 허용해야 합니다. .conf 파일에서 포트 번호를 확인한 다음 (remote로 시작하는 줄에 있습니다) 포트 번호와 인터페이스 이름을 바꾼 후 다음 명령을 실행합니다:

sudo iptables -A OUTPUT -o enp2s0 -p udp --dport 1194 -m comment --comment "OpenVPN traffic" -j ACCEPT

이제 서버의 NTP/DNS/DHCP 서비스를 허용해야 합니다:

sudo iptables -A OUTPUT -o eth0 -p udp --dport 123 -m comment --comment "NTP service" -j ACCEPT
sudo iptables -A OUTPUT -p UDP --dport 67:68 -m comment --comment "DHCP service" -j ACCEPT
sudo iptables -A OUTPUT -o eth0 -p udp --dport 53 -m comment --comment "DNS service" -j ACCEPT

거의 다 됐습니다. 이제 터널의 트래픽을 이더넷 인터페이스로 포워드해야 합니다. 이 부분이 가장 중요합니다. 인터페이스 이름을 바꾼 후 다음 명령을 실행합니다:

sudo iptables -A FORWARD -i tun0 -o enp2s0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i enp2s0 -o tun0 -m comment --comment "Local network to VPN" -j ACCEPT

마지막으로 NAT (Network Address Translation)이 VPN에서 동작하도록 POSTROUTING 테이블에서 MASQUERADE를 설정해야 합니다. 인터페이스 이름을 바꾼 후 다음 명령을 실행합니다:

sudo iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

여기까지 왔다면 축하합니다! 하지만 서버에서 로그아웃하기 전에 이 설정을 저장해야 재부팅 시 설정이 유지됩니다.

다음 프로그램을 설치합니다:

sudo apt install iptables-persistent

설치하면서 현재 설정 사항을 저장할지 묻는다면 예를 선택하고 진행합니다. 서비스가 부팅 시 시작되도록 다음 명령을 실행합니다:

sudo systemctl enable netfilter-persistent

나중에 iptables 룰을 더 추가한다면 이 명령을 실행하면 됩니다:

sudo netfilter-persistent save

그럼 설정값이 재부팅 시 적용됩니다.

마지막으로, 설정을 백업하고 싶으시다면 다음을 실행하면:

sudo iptables-save > backup.txt

설정값이 텍스트 파일에 저장됩니다. 저처럼 iptables에 자신이 없으시다면 이렇게 백업을 하신 다음 백업 파일을 편집하신 후 다시 적용해도 됩니다. 적용할 때엔 다음 명령을 사용합니다:

sudo iptables-restore < backup.txt

이제 설정 부분은 다 마쳤습니다.

연결 확인하기

서버를 재시작한 다음, 확인하고 싶은 기기에서 기본 게이트웨이의 주소를 서버/VM의 IP로 변경합니다. 그럼 기기의 트래픽이 VPN을 통해 전송됩니다. 여기까지 된다면 성공한 것입니다!

하지만 모든 기기마다 기본 게이트웨이를 변경하는 건 귀찮습니다. 그래서…

라우터 포워딩 설정하기

라우터에서 기본 게이트웨이 설정의 변경을 허용하는 경우, 이 부분도 따라하실 수 있습니다. (거의 대부분의 라우터가 이 설정을 지원합니다.)

아까 라우터 관리자 페이지에 접속 후, DHCP 설정을 선택합니다. 기본 게이트웨이 IP 주소 아래 VM/서버의 IP 주소를 입력합니다.

설정을 저장한 후, 라우터를 재부팅시킵니다. 이제 연결된 기기를 확인합니다. 만약 인터넷 연결이 정상적으로 동작한다면 완료된 것입니다!

만약 기본 게이트웨이 IP 주소를 변경했는데 관리자 페이지의 IP 주소가 새 기본 게이트웨이 IP 주소로 변경된다면, 주소 충돌로 인해 VM/서버가 IP 주소를 잃거나 로컬 네트워크에서 연결이 끊길수도 있습니다. 최악의 경우에는 라우터의 관리 페이지가 동작하지 않을수도 있습니다. 만약 이런 문제가 발생한다면, VM/서버를 네트워크에서 분리하고, 라우터를 재시작한 후 관리자 페이지에서 기본 게이트웨어 설정을 원래대로 변경하면 됩니다. 이렇게 설정 변경이 안 된다면 라우터에서 기본 게이트웨이 설정 변경을 지원하지 않아서 발생하는 문제입니다.

연결 도우미 스크립트

중국에선 수시로 VPN 연결을 끊어먹기 때문에, 매번 VM/서버에 다시 접속해서 연결을 재시작시켜주는 것이 귀찮아서 파이썬으로 연결 과정을 도와주는 스크립트를 작성했습니다.

만약 추가로 변경 사항이 있다면 깃허브 pull request로 보내주세요!

댓글