Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>

Contents

OpenVPN을 이용한 VPN 환경 구축

OpenVPN은 오픈 소스 프로그램으로 가상 사설망을 구축할 수 있는 소프트웨어다. 이와 비슷한 프로토콜로 PPTP와 L2TP/IPsec이 있다. 최근의 추세는 IPsec 혹은 OpenVPN 중 하나로 구축하는 것 같다. IPSec은 하드웨어 장비를 통해서 구현하는 경우가 많은데, 음.. 글쎄 돈이 남아돌지 않는다면 굳이 IPSec 기반으로 구현할 필요가 있을까 라는 생각을 해본다. 각 프로토콜에 대해서 궁금한 점은 vpn 프로토콜 비교문서를 참고하자. OpenVPN은 SSL기반의 VPN으로 openssl라이브러리를 사용한다.

위의 그림은 OpenVPN 서버와 클라이언트에 tun 디바이스가 만들어지고, 이 디바이스를 이용해서 10.8.0.0 주소영역을 가지는 사설망이 만들어 진것을 보여준다.

TUN방식은 다음과 같은 장점을 가진다.
  • 네트워크 디바이스를 생성함으로써, 네트워크 구조가 명확하고 비교적 안정적으로 작동한다는 장점을 가진다.
  • 고정 IP를 할당할 수 있어서 위치에 관계 없이 안정적으로 사설망을 유지할 수 있도록 한다.
  • 사설망을 위한 DHCP, 네임서버를 구축할 수 있다.

기본 원리

VPN은 물리적으로 떨어져 있는 두개의 네트워크를 가상의 네트워크로 묶는 개념이다. 두개 이상의 네트워크를 하나의 네트워크처럼 보이게 하려면 어떻게 해야 할까 ? Tunnel(터널)을 뚫으면 된다.

아래와 같이 간단하게 설명할 수 있다.

  • 10.10.0.0/16 네트워크와 10.50.0.0/16 네트워크가 internet(public network)를 사이에 두고 서로 떨어져 있다. 이들 네트워크는 사설 네트워크이기 때문에 트래픽을 전달할 수 없다.
  • 하지만 사설 네트워크에는 internet으로 트래픽을 보내기 위한 gateway가 있을 것이고, 이들은 public ip를 가지고 있을 것이다.
두 개의 사설 네트워크가 gateway를 통해서 연결이 되므로, 원칙적으로 사설 네트워크 끼리 통신이 가능하다.. 편지를 보내는 것처럼, 패킷을 한번 더 싸서 보내면 된다.

  1. 10.10.5.7 호스트가 10.50.50.2 호스트로 데이터를 보내려고 한다.
  2. 이 패킷의 src ip는 10.10.57.7 dst ip는 10.50.50.2 다.
  3. 패킷이 vpn 서버로 전달되면, vpn 서버는 public ip로 패킷을 둘러싼다. VPN 서버는 호스트가 보낸 패킷을 데이터로 하는 TCP/IP 패킷을 만든다.
  4. 이 패킷은 인터넷을 가로질러서 목적지까지 도착한다.
  5. 목적지의 vpn 서버는 패킷을 깐다.
  6. 패킷을 까면 원래 보내고자 하는 패킷이 나오고, 목적지 호스트로 전달할 수 있다.
  7. 응답 패킷은 정확히 반대의 과정을 거친다.
실제로는 더 복잡한 과정을 거치지만 이 정도면 알고 있으면, 쉽게 응용할 수 있다.

테스트 환경

VPN를 제대로 테스트 하려면 최대한 3대의 컴퓨터가 필요할 것이다. 그러나 굳이 그럴 필요가 없다. PC 가상화 솔류션이 있기 때문이다. 나는 PC 가상화 솔류션 중 하나인 VirtualBox를 이용 해서 VPN 테스트 환경을 만들었다.

호스트 운영체제는 우분투 리눅스 10.04 이며, 게스트 운영체제로는 Windows XP와 우분투 리눅스를 설치했다. 이 환경에서 VPN 테스트를 할 것이다.

OpenVPN 서버 설치

Ubuntu

VPN GW에 해당 하는 OpenVPN 서버를 설치하고 설정하는 과정을 정리한다. 우분투 리눅스 10.0.4를 기준으로 한다.
  1. openvpn 패키지를 설치한다.
    # sudo apt-get install openvpn
  2. openvpn의 설정파일의 위치를 지정한다. /etc/openvpn으로 했다.
    # echo "AUTOSTART=\"openvpn\"" >> /etc/default/openvpn
  3. ras 설정을 해야 한다. 상당히 복잡한 과정이지만, openvpn설치시 제공되는 예제 파일을 이용해서 비교적 간단히 설치할 수 있다.
    # cp -r /usr/share/doc/openvpn/examples/easy-rsa/ /etc/openvpn 
  4. var 파일은 ras 설정을 위한 환경 변수를 담고 있다. source명령을 이용해서 환경을 설정한다.
    # source /etc/openvpn/easy-rsa/2.0/vars
  5. private key를 만든다. 이제 부터 작업 디렉토리는 /etc/openvpn/easy-rsa/2.0이다. Sign the certificate1 out of 1 certificate ...는 모두 y를 선택한다.
    root:/etc/openvpn/easy-rsa/2.0# ./build-ca 
    Generating a 1024 bit RSA private key
    ....++++++
    ...............................++++++
    writing new private key to 'ca.key'
    -----
    ....
    ....
    
    Sign the certificate? [y/n]:y
    1 out of 1 certificate requests certified, commit? [y/n]y
  6. 서버 key를 만든다. 역시 Sign the...1 out of 1 certi...를 y로 한다.
    # root:/etc/openvpn/easy-rsa/2.0# ./build-key-server server
    Generating a 1024 bit RSA private key                                                           
    ................++++++
    ......................++++++                                                                    
    writing new private key to 'server.key'
    -----                                                                                           
    ....
    ....
    ....
    Sign the certificate? [y/n]:y
    1 out of 1 certificate requests certified, commit? [y/n]y
  7. client key를 만든다. 계정/암호 인증방식이 아닌 key를 이용한 인증방식시 사용한다. 이 키를 클라이언트에 배포하면, 클라이언트는 계정/암호 없이 서버에 연결할 수 있다. 키는 말그대로 서버에 드나들기 위한 열쇠이므로 배포시 보안에 주의해야 한다. 메일이나 ftp등으로 배포하는 일이 없도록 한다. client key는 클라이언트마다 필요하다. 그러므로 만약 100명의 클라이언트를 관리해야 한다면, 100개의 client key를 만들어야 한다. yundream이라는 이름의 client key를 만들기로 했다. 위의 키 생성과정과 동일하다.
    #root:/etc/openvpn/easy-rsa/2.0# ./build-key yundream 
  8. Diffie Hellman 파라메터를 생성한다.
    root@yundream-laptop:/etc/openvpn/easy-rsa/2.0# ./build-dh 
    Generating DH parameters, 1024 bit long safe prime, generator 2
    This is going to take a long time
    .......................................
이로서 서버측 설정을 마치고, yundream사용자를 위한 key도 만들었다. yundream 사용자에게 아래의 key를 배포하면 됩니다.
ca.crt
yundream.crt
yundream.key

CentOS

CentOS 6.3을 기준으로 한다. 우분투리눅스는 기본 레포지토리에서 openvpn을 제공하지만, centos는 EPEL레포지토리를 등록해야 한다.
# wget http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
# rpm -Uvh epel-release-6-8.noarch.rpm
# yum install openvpn -y 

키 관리를 도와주는 easy-rsa를 따로 설치해야 한다. (귀찮다)
# yum install easy-rsa

easy-rsa 파일들을 /etc 밑에 복사한다.
# cp -rf /usr/share/easy-rsa/2.0/* /etc/openvpn/easy-rsa

OpenVPN은 OpenSSL 라이브러리를 사용한다. 이를 위해서 openssl 설정파일을 만들어야 하는데, 미리 만들어져 있는 예제 설정파일을 복사해서 사용하면 된다. openssl 버전에 맞는 파일을 사용하자. "최대한 편하고 쉽게!!!" easy-rsa를 설치한 이유다.
cp /etc/openvpn/easy-rsa/openssl-1.0.0.cnf /etc/openvpn/easy-rsa/openssl.cnf

easy-rsa 디렉토리 밑에 있는 vars 파일을 편집한다. 다른 건 수정할 필요 없다. "KEY_"로 시작하는 변수들만 수정하자.
# vi /etc/openvpn/easy-rsa/vars
대략 아래와 같은 환경변수들을 수정하면 된다.
export KEY_COUNTRY="US"
export KEY_PROVINCE="NY"
export KEY_CITY="New York"
export KEY_ORG="Organization Name"
export KEY_EMAIL="administrator@example.com"
export KEY_CN=droplet.example.com
export KEY_NAME=server
export KEY_OU=server

var를 적용하고, key를 빌드하기 시작한다.
# cd /etc/openvpn/easy-rsa
# source ./vars
# ./clean-all
# ./build-ca
OpenVPN 서버를 위한 CA를 만든다.
# ./buid-key-server server

Diffie Hellman key를 만든다. dh 키와 함께 build-key-server로 만든 키 파일들을 openvpn 디레고리로 복사한다.
# ./build-dh
# cd keys
# cp dh1024.pem ca.crt server.crt server.key /etc/openvpn 

서버를 시작하면 끝. 클라이언트 키를 만들고 유지하는 것은 우분투리눅스의 openvpn과 동일하므로 생략한다.

OpenVPN 서버 설정

이제 남은 건 설정파일이다. OpenVPN을 소개하는 책이 따로 출판되었을 정도로 OpenVPN은 많은 기능을 제공한다. 여기에서는 TUN 디바이스를 이용해서 step 3 VPN 환경 구축을 할 것이다.

  1. 설정파일 복사
예제 설정파일인 /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz을 /etc/openvpn/openvpn.conf로 복사해서 사용하기로 했다.
  1. key 위치 지정. 다음의 key 파일의 위치만 조절해 주면 된다. 현재 우리가 만든 키는 /etc/openvpn/easy-rsa/2.0/keys 디렉토리 밑에 있다.
    ca /etc/openvpn/easy-rsa/2.0/keys/ca.crt
    cert /etc/openvpn/easy-rsa/2.0/keys/server.crt
    key /etc/openvpn/easy-rsa/2.0/keys/server.key  # This file should be kept secret
    dh /etc/openvpn/easy-rsa/2.0/keys/dh1024.pem
  2. 기타 주요 설정. 주석으로 설명을 대신한다.
    # udp 1194를 사용한다.
    proto udp
    
    # tun 디바이스를 사용한다.
    dev tun
    
    # 서버 key 값 설정
    ca /etc/openvpn/easy-rsa/2.0/keys/ca.crt
    cert /etc/openvpn/easy-rsa/2.0/keys/server.crt
    key /etc/openvpn/easy-rsa/2.0/keys/server.key  # This file should be kept secret
    dh /etc/openvpn/easy-rsa/2.0/keys/dh1024.pem
    
    # VPN 네트워크 영역을 지정한다. 기본으로 10.8.0.0을 사용한다.
    server 10.8.0.0  255.255.255.0
    
    # subnet에 접근하는 것을 허락한다.
    push "route 10.8.0.0  255.255.255.0"
    
    client-to-client
  3. 테스트. /etc/init.d/openvpn 스크립트를 이용해도 되지만, 에러 메시지 확인을 위해서 쉘에서 직접 실행했다.
    # openvpn --config /etc/openvpn/openvpn.conf
  4. 성공적으로 실행했다면, tun 디바이스를 확인할 수 있을 것이다.
    # ifconfig
    ......
    tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
              inet addr:10.8.0.1  P-t-P:10.8.0.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은 key 인증외에 PAM 모듈 인증을 허용한다. 이 모듈을 이용하면, 아이디/패스워드 인증까지 함께 사용할 수 있다.

서버측 설정파일에 아래 내용을 추가한다.
# so 파일의 경로는 배포판에 따라서 약간식 다를 수 있다.
plugin /usr/lib/openvpn/openvpn-pam-auth.so login

클라이언트 설정파일에 다음의 내용을 추가한다.
auth-user-pass
이제 vpn 클라이언트를 실행하면, 아이디 패스워드를 묻는 걸 확인할 수 있을 것이다.

Host to Site VPN

VPN server를 gateway로 해서 Gateway가 관리하는 subnet에 접근을 원할 때가 있다. 그림과 같은 경우다.

  • VPN GW의 가상 인터페이스 주소 : 192.168.100.1
  • VPN에서 관리하는 가상 네트워크 주소 : 192.168.100.0
  • VPN GW에서 관리하는 subnet 주소 : 192.168.56.0
원하는 것은 VPN Client가 192.168.56.0의 주소를 가지는 컴퓨터에 접근하도록 하는 것이다. VPN 서버의 설정파일에 아래의 부분을 추가한다.
push "route 192.168.56.0 255.255.255.0 192.168.100.1"
push는 클라이언트에 설정값을 밀어 넣기 위해서 사용한다. 아래의 명령은 클라이언트로 하여금 다음과 같이 라우팅 테이블을 설정하도록 할 것이다.
yundream@yundream-desktop:~$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.100.0   192.168.100.1   255.255.255.0   UG    0      0        0 tun0
192.168.100.0   *               255.255.255.0   U     0      0        0 tun0
192.168.1.0     *               255.255.255.0   U     2      0        0 wlan0
192.168.56.0    192.168.100.1   255.255.255.0   UG    0      0        0 tun0
...

이제 VPN 서버에서 IP forwarding이 가능하도록 설정한다.
  1. ip forwad가 가능하도록 한다.
    # echo 1 > /proc/sys/net/ipv4/ip_forward
  2. ip_forward 값은 리부팅 때마다 기본값인 0으로 재 설정된다. 기본 값을 1로 하고 싶다면, /etc/sysctl.conf에 아래와 같이 설정하면 된다.
    net.ipv4.ip-forward = 1
  3. tun 디바이스를 ip forwarding 가능하도록 한다.
    # iptables -A INPUT -i tun+ -j ACCEPT
    # iptables -A FORWARD -i tun+ -j ACCEPT

OpenVPN 클라이언트 설치

OpenVPN은 클라이언트와 서버 구분이 없이 하나의 프로그램으로 배포된다. 설정파일로 서버로 실행될지 클라이언트로 실행될지가 결정된다.

OpenVPN 클라이언트 설정

설정은 리눅스와 윈도우 모두 동일하다. 다만 경로 설정 방식에 있어서 차이가 있을 뿐이다. 리눅스 클라이언트 설정파일을 수정해서 쓰면 된다. 유저 이름은 winvpn으로 Openvpn 서버에서 생성한 키 파일이다.
  1. openvpn 환경 설정을 위한 디렉토리를 만든다. 나는 /home/yundream/openvpn 디렉토리를 만들었다.
  2. key를 보관하기 위한 디렉토리를 만들었다. mkdir /home/yundream/openvpn/keys
  3. 클라이언트 키 파일을 복사해와서 위에서 만든 key 디렉토리에 위치한다. 키 인증 방식이 아닌 ID/PW 인증 방식을 사용할 수도 있는데, 이는 나중에 다뤄볼 생각이다.
  4. openvpn 설정 파일을 만들어야 하는데, 서버 설정파일과 마찬가지로 미리 만들어져 있는 셈플 설정파일을 약간 수정해서 사용하면 된다. /usr/share/doc/openvpn/examples/sample-config-files/client.conf파일을 /home/yundream/openvpn 디렉토리로 복사한다음 아래와 같이 수정했다.
    dev tun
    proto udp
    ...
    # openvpn 서버의 주소 정보
    remote 192.168.55.1 1194
    
    # 사용할 ip 대역
    ifconfig 10.8.0.2 10.8.0.1
    
    # key 위치
    ca /home/yundream/openvpn/keys/ca.crt
    cert /home/yundream/openvpn/keys/localvpn1.crt
    key /home/yundream/openvpn/keys/localvpn1.key
이제 OpenVPN 클라이언트를 실행하면 된다.
# sudo openvpn --config client.conf
ifconfig로 tun 드라이버를 확인해보자.
# ifconfig
...
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet addr:10.8.0.6  P-t-P:10.8.0.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)

윈도우도 리눅스와 동일하다. 설정파일에서 ca 파일의 경로만 다르게 하면 된다. openvpn을 실행하면 tray에 아이콘이 생기는걸 확인할 수 있다. connect를 클릭하면 연결이 진행된다. 성공적으로 실행된 다음에 ipconfig로 확인해 보면 TUN 드라이버가 생긴걸 확인할 수 있을 것이다.
Ethernet adapter 로컬 영역 연결 3:

        Connection-specific DNS Suffix  . :
        Description . . . . . . . . . . . : TAP-Win32 Adapter V9
        Physical Address. . . . . . . . . : 00-FF-60-C7-BD-75
        Dhcp Enabled. . . . . . . . . . . : Yes
        Autoconfiguration Enabled . . . . : Yes
        IP Address. . . . . . . . . . . . : 10.8.0.14
        Subnet Mask . . . . . . . . . . . : 255.255.255.252
        IP Address. . . . . . . . . . . . : fe80::2ff:60ff:fec7:bd75%4
        Default Gateway . . . . . . . . . :
        DHCP Server . . . . . . . . . . . : 10.8.0.13
        DNS Servers . . . . . . . . . . . : fec0:0:0:ffff::1%1
                                            fec0:0:0:ffff::2%1
                                            fec0:0:0:ffff::3%1
        Lease Obtained. . . . . . . . . . : 2010년 9월 20일 월요일 오후 5:24:35
        Lease Expires . . . . . . . . . . : 2011년 9월 20일 화요일 오후 5:24:35

서로 연결이 되는지 ping을 이용해서 테스트해 보고, 문제가 없다면 ssh 연결등도 테스트 해보자.

Site-to-Site VPN