본문 바로가기

IT-Consultant

OpenVPN설치기


 

몇 년 전 외부에서 사내네트웍의 안전한 접근을 위하여 고민할 때 VPN에 대한 고려를 하였었습니다.
하지만 VPN에 대한 지식이 부족하여 실행하지는 못하고 well-known port의 blocking및 IPSec등을
통하여 보안작업을 했었습니다.

이런 작업에도 불구하여 여전히 보안상 위험은 상존하고 있습니다.
1. IPSec의 보안key가 노출될 경우
2. 외부PC<->사무실PC로의 traffic이 packet sniffing등을 통하여 노출될 수 있음.

이런 상황에서 괜찮은 무료 VPN S/W가 있다는 것을 확인하여(OpenVPN) 설치해 보았습니다.

<필요한 Knowhow>
1. linux의 간단한 패키지 설치 지식
2. VPN에 대한 개괄적인 지식
3. NSIS(무료 소프트웨어 인스톨러 제작 프로그램)를 통한 간단한 패키지 작성
4. linux의 간단한 네트웍 설정(ipforward, NAT)
5. routing table 조정 지식
6. windows및 linux의 packet capture S/W 사용법(ethereal, tcpdump)

*관련하여 작업중 기본기가 부족하여 여러가지 어려움에 봉착했으며, 이를 여과없이 기술하여 전혀
 지식이 없는 분들도 이해하기가 어렵지 않도록 history를 기술하겠습니다.


<OpenVPN 서버 설치>
1. OpenVPN데몬 설치 서버 선택 : VPNSVR(XXX.XXX.XXX.XXX)

2. 관련 package download
 a. lzo 2.0 : http://www.oberhumer.com/opensource/lzo/download/
 b. OpenSSL 0.9.7a : http://www.openssl.org/source
 c. OpenVPN : http://www.openvpn.net/index.php/downloads.html

3. 관련 package설치
 a. 소스 압축 해제 : /usr/local/src
 b. 컴파일
  -lzo 2.0
   ./configure --prefix=/usr/local/lzo
   make
   make install
  -openssl 0.9.7a
   ./config --prefix=/usr/local/openssl-0.9.7a
   make
   make install
  -openvpn
   ./configure --prefix=/usr/local/openvpn2.0.9 --with-lzo-headers=/usr/local/lzo/include --with-lzo-lib=/usr/local/lzo/lib --with-ssl-headers=/usr/local/openssl-0.9.7a/include --with-ssl-lib=/usr/local/openssl-0.9.7a/lib
   make
   make install
 c. 주요 디렉토리 생성
  -mkdir ${OPENVPN_DIR}/plugin
  -mkdir ${OPENVPN_DIR}/clientkeys
  -mkdir ${OPENVPN_DIR}/keys
  -mkdir ${OPENVPN_DIR}/log
 d. linux사용자로 인증을 하기 위한 plugin컴파일
   -${OPENVPN_SRC_DIR}/plugin/auth-pam/에서 make실행
    *이때 pam-appl.h등 pam관련 header파일을 못찾는 에러가 발생함.
     ->VPN서버에는 pam-devel패키지가 설치가 되어 있지 않아서 그런 것으로 판단하고 나 유사 linux시스템에서
       관련 header들을 복사.(user/include/security 디렉토리)
   -생성된 openvpn-auth-pam.so를 openvpn이 설치된 디렉토리에 plugin 디렉토리로 복사
    (/usr/local/openvpn2.0.9/plugin/openvpn-auth-pam.so)

4. openvpn설정파일 조정
 a. 샘플 openvpn.conf를 복사 : cp ${OPENVPN_SRC_DIR}/sample-config-files/server.conf /usr/local/openvpn2.0.9/openvpn.conf
 b. 수정
--------------------------------------------------------------
#실제로 서버에서 생성한 key파일 및 certificates에 대한 위치를 지정
ca /usr/local/openvpn2.0.9/keys/ca.crt
cert /usr/local/openvpn2.0.9/keys/server.crt
key /usr/local/openvpn2.0.9/keys/server.key  # This file should be kept secret

#key negociation에 필요한 Diffie hellman parameter설정(기본은 1024나 보안을 위하여 2048로 변경)
dh /usr/local/openvpn2.0.9/keys/dh2048.pem

#접속허가된 IP들에 대한 list저장 파일 지정
ifconfig-pool-persist /usr/local/openvpn2.0.9/ipp.txt

#client의 모든 traffic을 VPN을 통하도록 설정
push "redirect-gateway def1"
!위와 같이 설정하면 모든 traffic이 VPN을 통과하게 되므로 부담이 될 수 있다. 따라서 VPN을 통해야만 하는
네트웍을 지정하려면 push "route ..."를 추가하면 된다.
(당연히 push "redirect-gateway def1"은 주석처리해야 한다.)
예를 들어, 203.238.211.160(255.255.255.224) 네트웍만 VPN을 통하게 하려면 아래와 같이 설정한다.
push "route 203.211.111.160 255.255.255.224" #my secured network
!만약 상기에 지정하는 network안에 VPN서버가 포함되어 있다면 이는 제외를 해줘야 한다.
이때는 아래와 같이 VPN서버는 기존의 gateway를 통하여 처리하라는 라인을 추가한다.
push "route remote_host 255.255.255.255 net_gateway" #exclude vpn server itself

#현재 VPN의 접속상태를 기록하는 log위치 지정
status /usr/local/openvpn2.0.9/log/openvpn-status.log

#VPN 데몬의 모든 로깅 파일 위치 지정
log         /usr/local/openvpn2.0.9/log/openvpn.log

#linux사용자 계정으로 인증을 하며 client가 개인 certificate를 가지지 않아도 되도록 설정
#개인key를 개인들에게 배포하기가 힘들기 때문
plugin /usr/local/openvpn2.0.9/plugin/openvpn-auth-pam.so login
client-cert-not-required
username-as-common-name
--------------------------------------------------------------

5. openssl설정 조정 및 필요한 key및 certificate생성
 a. 샘플 openssl.cnf를 복사 : cp ${OPENVPN_SRC_DIR}/easy-rsa/openssl.cnf /usr/local/openvpn2.0.9/
 b. 수정
--------------------------------------------------------------
#기본적으론는 소스가 설치된 디렉토리에 작성을 하도록 되어 있었으므로 이를 수정
dir             = /usr/local/openvpn2.0.9/keys          # Where everything is kept
--------------------------------------------------------------
 c. 환경변수 export(*이부분은 key와 certificate생성시 입력이 필요한 부분인데 편의성을 위해서 처리)
--------------------------------------------------------------
export D=/usr/local/openvpn2.0.9/
export KEY_CONFIG=$D/openssl.cnf
export KEY_DIR=$D/keys
export KEY_SIZE=2048
export KEY_COUNTRY=KR
export KEY_PROVINCE=NA
export KEY_CITY=SEOUL
export KEY_ORG="abc inc"
export KEY_EMAIL="vpnadmin@abc.com"
--------------------------------------------------------------
 d. openssl이 사용하는 중요 파일들 설정
--------------------------------------------------------------
touch /usr/local/openvpn2.0.9/keys/index.txt -> index.txt파일 생성
echo 01 > /usr/local/openvpn2.0.9/keys/serial -> serial파일을 만들면서 01로 초기화
--------------------------------------------------------------
 e. 서버에서 사용할 key생성(*ca.crt의 경우 client로도 전달이 되어야 함)
   *client에서 사용할 개인 certificate는 생성하지 않음.
--------------------------------------------------------------
/usr/local/openssl-0.9.7a/bin/openssl req -days 365 -nodes -new -x509 -keyout /usr/local/openvpn2.0.9/keys/ca.key -out /usr/local/openvpn2.0.9/keys/ca.crt -config /usr/local/openvpn2.0.9/openssl.cnf
/usr/local/openssl-0.9.7a/bin/openssl req -days 365 -nodes -new -keyout /usr/local/openvpn2.0.9/keys/server.key -out /usr/local/openvpn2.0.9/keys/server.csr -extensions server -config /usr/local/openvpn2.0.9/openssl.cnf
/usr/local/openssl-0.9.7a/bin/openssl ca -days 365 -out /usr/local/openvpn2.0.9/keys/server.crt -in /usr/local/openvpn2.0.9/keys/server.csr -extensions server -config /usr/local/openvpn2.0.9/openssl.cnf
/usr/local/openssl-0.9.7a/bin/openssl dhparam -out /usr/local/openvpn2.0.9/keys/dh2048.pem 2048
--------------------------------------------------------------

6. 서버 실행
   /usr/local/openvpn2.0.9/sbin/openvpn --config /usr/local/openvpn2.0.9/openvpn.conf --daemon --mode server
  *이 때 "AUTH-PAM: BACKGROUND: could not load PAM lib libpam.so" 에러가 발생함
   ->linux계정으로 인증을 받기 위해서 load되는 openvpn-auth-pam.so에서 pam library를 사용하는데 이를 못찾음.
     VPN서버에서 사용하는 pam library는 libpam.so.0.75인데 libpam.so.0으로만 symbolic link되어 있었음.
     ln -s /lib/libpam.so.0.75 /lib/libpam.so 로 libpam.so로 추가 link
 a. VPN을 통한 VPN서버외 다른서버(internet상의 모든 서버 포함)로 접근을 위해 네트웍 세팅 변경
  -echo 1 > /proc/sys/net/ipv4/ip_forward
   *이는 서버가 내려갔다 올라오면 다시 변경되므로 /etc/sysctl.conf의 값도 변경해야 함(net.ipv4.ip_forward = 1)
   */etc/sysctl.conf를 변경한 후 적용하려면 sysctl -p로 반영 가능
  -iptables -A INPUT -i tun+ -j ACCEPT
  -iptables -A FORWARD -i tun+ -j ACCEPT
   *VPN에서 사용하는 tun device에 대해서 ipforward기능 on
  -iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
   *다른 서버로 접근이 가능하도록 nat설정
  !!iptables설정값을 시스템 재시작 때도 적용이 되도록 영구 저장
   /sbin/service iptables save

 b. 서버 작동 확인
  -OpenVPN log들
  -tcpdump를 통한 해당 port(1194) 패킷 모니터링
   tcpdump -n udp port 1194
  -실제 traffic이 VPN을 통해서 나가고 있는지 연결된 client의 packet확인
   tcpdump -n host XXX.XXX.XXX.XXX


<OpenVPN GUI client 설치>
1. NSIS(Nullsoft Scriptable Install System) V2.35 download
  http://nsis.sourceforge.net/Main_Page

2. OpenVPN에서 제공하는 NSIS용 package download
  http://www.openvpn.se/files/install_packages_source/

3. 서버에서 작성한 ca.crt파일 download

4. OpenVPN Gui용 설정파일 복사하여 수정
  #2에서 download받은 파일의 압축해제 후 sample-config파일의 client.ovpn사용
--------------------------------------------------------------
#접속할 VPN서버 지정
remote XXX.XXX.XXX.XXX 1194

#사용할 key와 certificate지정
#개인별 client key와 certificate는 사용하지 않을 것이므로 주석처리
ca "ca.crt"
;cert "client.crt"
;key "client.key"

#linux계정 인증을 사용
auth-user-pass
--------------------------------------------------------------

5. 수정한 client.ovpn파일과 ca.crt파일을 #2에서 압축해제하여 생성된 openvpn폴더의 config폴더에 복사

6. openvpn-gui.nsi파일 수정
--------------------------------------------------------------
#컴파일시 aleady defined에러가 발생하여 주석처리
;!define SF_SELECTED   1
;!define SF_RO         16
;!define SF_NOT_RO     0xFFFFFFEF

#작성한 설정파일과 서버의 ca.crt파일 복사
File "${HOME}\config\client.ovpn"
File "${HOME}\config\ca.crt"

#복사된 설정파일과 서버의 ca.crt파일 uninstall시 삭제(uninstall section)
Delete "$INSTDIR\config\ca.crt"
Delete "$INSTDIR\config\client.ovpn"
 
#기본적으로 설치하지 않아도 되는 것들에 대한 주석처리
  ;Disable AutoStart OpenVPN GUI
  SectionSetFlags ${SecGUIAuto} 0

  ;Disable Add OpenVPN to PATH
  SectionSetFlags ${SecAddPath} 0

  ;Disable OpenSSL Utilities
  SectionSetFlags ${SecOpenSSLUtilities} 0

  ;Disable OpenVPN Service
  SectionSetFlags ${SecService} 0

  ;Disable OpenVPN RSA Certificate Management Script
  SectionSetFlags ${SecOpenVPNEasyRSA} 0
--------------------------------------------------------------

7. openvpn-gui.nsi을 컴파일
[그림]패포판 생성


8. 생성된 exe파일로 설치

9. 연결후 연결확인

[그림]연결 요청


[그림]linux계정을 통한 인증 요청

[그림]연결된 화면

[그림]조정된 client의 routing table확인

[그림]client에서 web browsing시 packet capture
*모두 VPN서버의 1194포트포 UDP패킷이 전달되는 것을 알 수 있음.

[그림]서버 packet caputure
 *client에서 특정서버로 ping 패킷을 보내면 VPN서버를 통해 전달되는 것을 확인

<OpenVPN을 linux시작시 자동으로 시작되도록 등록>
1. /etc/rc.d/init.d에 script작성
!smb(삼바서버용 script)를 수정하여 작성
--------------------------------------------------------------
#!/bin/sh
#
# chkconfig: - 91 35
# description: Starts and stops the Openvpn server.
#
# config:  /usr/local/openvpn2.0.9/openvpn.conf


# Source function library.
if [ -f /etc/init.d/functions ] ; then
  . /etc/init.d/functions
elif [ -f /etc/rc.d/init.d/functions ] ; then
  . /etc/rc.d/init.d/functions
else
  exit 0
fi

# Avoid using root's TMPDIR
unset TMPDIR

# Source networking configuration.
. /etc/sysconfig/network

# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0

# Check that smb.conf exists.
[ -f /usr/local/openvpn2.0.9/openvpn.conf ] || exit 0

# Check that we can write to it... so non-root users stop here
#[ -w /user/local/openvpn2.0.9/openvpn.conf ] || exit 0

RETVAL=0
KIND="OpenVPN"

start() {
        echo -n $"Starting $KIND services: "
        daemon /usr/local/openvpn2.0.9/sbin/openvpn --config /usr/local/openvpn2.0.9/openvpn.conf --daemon --mode server
        RETVAL=$?
        [ $RETVAL -eq 0 ]
        echo ""
        return $RETVAL
}

stop() {
        echo -n $"Shutting down $KIND services: "
        killproc openvpn
        RETVAL=$?
        [ $RETVAL -eq 0 ]
        echo ""
        return $RETVAL
}

restart() {
        stop
        start
}

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        restart
        ;;
  *)
        echo $"Usage: $0 {start|stop|restart}"
        exit 1
esac

exit $?
--------------------------------------------------------------

2. runlevel별로 수행되거나 종료될 수 있도록 chkconfig를 사용하여 등록
/etc/rc.d/init.d/chkconfig --add openvpn
[그림]chkconfig로 등록후 결과 확인(chkconfig --list)


runlevel 3(full multiuser mode)과 5(X11 mode)에는 수행이 되도록 할 것이므로 아래의 명령 수행
chkconfig --level 35 openvpn on
[그림]결과 확인(chkconfig --list)
[그림]각 runlevel이 관리되는 폴더에 symbolic link작성된 것 확인



!이후 추가적으로 해야할 작업들과 관리작업들이 있지만 설치와 연결에 중점을 두었기에 여기까지만 기술합니다.

[참조자료]
1. OpenVPN에 대해서 잘 정리된 naver cafe article : http://cafe.naver.com/01064503523/541
2. chkconfig사용법 : http://blog.naver.com/couplewith/60007889350
3. OpenVPN관련 책자 : OpenVPN
 -저자 : Markus Feilner
 -출판사 : PACKT publishing
 -출간일 : 2006-05
 -ISBN 190481185X
 -ISBN 13 978-1-904811-85-5
 *국내에는 원서도 번역서도 판매가 되지 않아 https://www.packtpub.com/에서 online ebook구매