VPN은 Virtual Private Network의 약어로, OpenVPN을 사용하면 같은 네트워크에 포함되어 있지 않은 자원들을 ‘가상으로 만들어진’ 하나의 네트워크로 묶을 수 있다.

위 그림은 일반적으로 사용하는 OpenVPN 서버/클라이언트 모델이다. TUN 디바이스를 사용하여 터널을 구축하였을 경우 패킷의 흐름은 위와 같다. Server #1에서 생성된 패킷의 목적지가 Server #2의 TUN Device IP라면 암호화된 터널을 지나 해당 디바이스에 도달할 것이다.

OpenVPN 설치

Ubuntu 16.04기준으로 다음과 같이 설치할 수 있다.

server-side$ sudo apt-get install openvpn

또한 easy-rsa를 사용하여 OpenVPN과 관련된 ca작업들을 간단한 cli로 처리할 수 있다. 이것 또한 함게 설치하도록 한다. 설치가 되는 경로는 /usr/share/easy-rsa이다.

server-side$ sudo apt-get install easy-rsa

간단한 준비는 완료되었으며 이제, 다음과 같은 방식으로 OpenVPN서버/클라이언트를 생성할 수 있다.

  1. easy-rsa를 사용하여 ca키 생성
  2. easy-rsa를 사용하여 dh키 생성
  3. easy-rsa를 사용하여 서버 키 생성
  4. easy-rsa를 사용하여 클라이언트 키 생성
  5. OpenVPN 서버 설정 생성 후 서버 실행
  6. OpenVPN 클라이언트 설정 생성 후 클라이언트 실행

easy-rsa 를 이용한 키 생성

easy-rsa는 쉘 스크립트로 이루어진 openssl 래퍼로, 이를 사용하기 위해서는 최초에 환경변수를 등록할 필요가 있다. 많은 값들이 필요하지만 기본적으로는 easy-rsa에 포함된 vars 파일을 읽어들이는 것으로 간단히 값을 지정할 수 있다. vars 파일을 그대로 읽어들여도 상관없고, 파일을 직접 열어서 export될 변수들을 변경해 주어도 된다. 준비가 모두 끝났다면 source를 통해 환경변수를 읽어들인다.

server-side:/usr/share/easy-rsa$ source vars
NOTE: If you run ./clean-all, I will be doing a rm -rf on /usr/share/easy-rsa/keys

또한 초기화 작업이 필요하다. clean-all을 실행하면 초기화 작업을 진행하며, 필요없는 파일이 있다면 삭제한 후 필요한 디렉토리와 정보를 생성하게 된다.

server-side:/usr/share/easy-rsa$ ./clean-all

먼저 ca를 생성해 보자. build-ca를 실행하면 된다.

server-side:/usr/share/easy-rsa$ ./build-ca
Generating a 1024 bit RSA private key
........................++++++
............................++++++
writing new private key to 'ca.key'
...

다음은 dh키를 생성해 보자.

server-side:/usr/share/easy-rsa$ ./build-dh
Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
.................................................+..........................................+..
...
++*++*++*

다음은 서버 키를 생성한다.

server-side:/usr/share/easy-rsa$ ./build-key-server server
Generating a 1024 bit RSA private key
..................................++++++
............................++++++
writing new private key to 'server.key'
...
Write out database with 1 new entries
Data Base Updated

마지막으로 클라이언트가 사용할 키를 생성한다.

server-side:/usr/share/easy-rsa$ ./build-key cublr
...
Write out database with 1 new entries
Data Base Updated
root@openvpn-server-side:/usr/share/easy-rsa$ cd keys/
root@openvpn-server-side:/usr/share/easy-rsa/keys$ ls | grep cublr
cublr.crt
cublr.csr
cublr.key

필요한 모든 키가 생성되었으므로, 이제 서버/클라이언트의 설정이 필요하다.

OpenVPN서버/클라이언트 설정

OpenVPN서버 설정

이번엔 서버의 설정이 필요하다. 서버의 설정 파일을 만드는 것이 꽤 복잡하나, 범용적인 사용을 위한 템플릿은 OpenVPN 설치 시 함께 설치된다.

server-side:/etc/openvpn$ cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
root@openvpn-server-side:/etc/openvpn$ gzip -d /etc/openvpn/server.conf.gz
root@openvpn-server-side:/etc/openvpn$ ls | grep server.conf
server.conf

여러 설정 항목들이 있지만 여기서는 간단히, 설정 파일의 server 부분에 새롭게 구성될 vpn의 subnet을 적어 주는 정도로만 수정했다. 이제 서버/클라이언트가 서로 연결되면 192.168.200.0/24의 대역을 가지는 네트워크로 묶일 수 있을 것이다.

# Configure server mode and supply a VPN subnet
# for OpenVPN to draw client addresses from.
# The server will take 10.8.0.1 for itself,
# the rest will be made available to clients.
# Each client will be able to reach the server
# on 10.8.0.1. Comment this line out if you are
# ethernet bridging. See the man page for more info.
server 192.168.200.0 255.255.255.0

...
...
...

OpenVPN서비스를 재시작하면 이제 tun0 디바이스가 생긴 것을 확인할 수 있다.

server-side:/usr/share/easy-rsa$ ifconfig tun0
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet addr:192.168.200.1  P-t-P:192.168.200.2  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

OpenVPN 클라이언트 설정

클라이언트 설정을 위해서는 서버와 마찬가지로 openvpn 패키지를 설치하면 된다. 서버/클라이언트 전용 프로그램이 있는 것이 아니고, 설정에 따라 서버와 클라이언트의 동작이 가능하기 때문이다.

client-side:~$ sudo apt-get install openvpn

서버에 접속하기 위해서는 서버 정보가 들어있는 config 파일, 그리고 서버의 키 파일, 그리고 서버에서 클라이언트를 위해 생성한 클라이언트 키 등이 필요하다. 먼저 서버에서 클라이언트의 키를 생성하자. 클라이언트가 서버에 접속하기 위해서는 다음의 파일이 필요하다.

  • ca.crt
  • client.crt
  • client.key
  • openvpn.conf

ca.crt, username.crt, username.key는 모두 서버에서 가져와야 한다. 이미 위에서 클라이언트 키를 생성했으므로, 생성한 파일을 그대로 클라이언트에서 사용하면 된다. openvpn.conf파일은 OpenVPN 클라이언트 설정 파일인데, 설정하기 어렵지만 이것도 OpenVPN 설치 시 템플릿이 함께 설치되므로 간단히 사용할 수 있다.

client-side:/etc/openvpn$ cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn

client.conf 내에서, 간단히 remote 부분에 서버의 Public IP를 적어주는 정도로만 수정했다.

# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
remote 12.34.56.78 1194

...
...
...

수정이 완료되었다면 다음의 명령으로 client쪽에서 OpenVPN을 재시작한다.

side:~/cublr-openvpn$ ls
ca.crt  cublr.crt  cublr.key  openvpn.conf
client-side:~/cublr-openvpn$ sudo openvpn --config openvpn.conf

네트워크 디바이스를 살펴보면 다음처럼 tun0이 추가되어 있는 것을 확인할 수 있다.

cublr@vpn-client-side:~/cublr-openvpn$ ifconfig tun0
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet addr:192.168.200.6  P-t-P:192.168.200.5  Mask:255.255.255.255
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

이제 OpenVPN 서버와 클라이언트는 192.168.200.0/24의 가상 네트워크로 묶이게 되었다.

client-side:~/cublr-openvpn$ telnet 192.168.200.1 22
Trying 192.168.200.1...
Connected to 192.168.200.1.
Escape character is '^]'.
SSH-2.0-OpenSSH_5.9p1 Debian-5ubuntu1.1