9월 142016
 

VPN은 외부로부터 격리된 인트라넷을 구성하면 외부에서 접속이 불가능한데 이를 가능하게 해주는 서비스이다. 물리적으로 서로 떨어져 있는 회사 네트워크를 외부에 공개하지 않으면서 통신하기 위해 만들어 졌다. 물론 회사 네트워크에서 사용하면 이런용도로 사용하게 되겠지만, 집에서 공유기 뒤에 NAS를 쓰거나, 개인 서버를 사용하는 경우에도 동일한 방법으로 활용할 수 있다. 만약 NAS나 개인서버를 SMB(네트워크 공유 기능)통해 사용하기 위해서는 같은 네트워크에 있어야 한다. 하지만 외부에서는 이 방법을 사용할 수 없는데, 이는 ISP(네트워크 제공사)의 방화벽 문제가 있기 때문이며, 따라서 WebDAV등을 이용하여 구현하는 방법이 일반적이다. 이 경우에 외부에는 내부 서버를 공개하지 않으면서 안전(암호화된)하게 내부 네트워크에 접속된 것과 같은 상태를 만들 수 있는 방법이 바로 VPN인 것이다.

일반적인 공유기는 VPN 프로토콜 중에 하나인 PPTP를 지원하도록 구현되어 있다. 하지만 PPTP의 문제는 인증시스템이나 암호화 방식이 매우 오래되었으며 보안에 취약하다는 점이다[1]. 그래서인지 이번에 업데이트 되는 iOS 10, macOS Sierra부터는 보안상의 이유로 더 이상 PPTP프로토콜 기반의 VPN서비스를 이용할 수 없게 되었다[2]. 하지만 필자가 가지고 있는 공유기에서 PPTP를 지원하지 않기 때문에 다른 프로토콜을 사용하는 VPN이 필요하게 되었다. 하지만 굳이 공유기에서 PPTP가 아닌 다른 프로토콜을 지원하게 하려면 공유기의 펌웨어를 커스터마이징해야 한다는 것인데 그건 너무 시간이 많이 걸리며 공유기 공급사에서 소스코드를 공개하지 않는다는 점에서 어려움이 있다. 따라서 VPN서버를 공유기에서 내부 서버로 변경하면 여러종류의 VPN프로토콜이 사용 가능해 지기 때문에 홈 서버에 VPN서버를 설치 하게 되었다. 좀 더 큰 CPU파워를 사용할 수 있게 됨으로써 최신 VPN 프로토콜과 고급 암호화 기능도 사용할 수 있게 되었다.

자료 조사를 해보면서 여러 종류의 VPN 프로토콜이 존재함을 알 수 있었으며, VPN 프로토콜을 선택 기준이 필요해 졌는데 모바일이나 OS에서 추가적인 프로그램 설치 없이 사용할 수 있어야 한다는 조건을 걸었다. 이 조건을 만족하면 모바일로 외부에서 집에 있는 서버에 있는 동영상을 스트리밍으로 볼 수 있기 때문에다. 이에 추가 클라이언트 환경 설치가 필요한 OpenVPN은 제외되었다. 그렇게 되면 가능한 프로토콜이 L2TP/IPSec, IPSec, IKEv2 를 사용할 수 있음을 확인 가능하였다. 최초에는 L2TP/IPSec을 이용할 예정이였으나, 필자가 사용하는 OS에서는 기본 지원하며, 속도도 빠르고 높은 보안을 제공하는 IKEv2 프로토콜을 이용하여 구현하기로 하였다[3].

IKEv2 프로토콜을 사용할 때 ESP를 통하여 암호화된 패킷을 전송한다. 원래 ESP는 IP프로토콜에 바로 들어가기 때문에 공유기(NAT)뒤에 VPN서버가 있는 경우에는 DMZ설정 같은 것이 필요하며 공유기가 이 기능을 지원해야할 수도 있다. DMZ로 설정하면 VPN서버의 모든 부분이 인터넷으로 공개되기 때문에 내부를 숨기겠다는 목적이 달성되지 않는다. 하지만 선배 개발자들은 이런 문제를 해결하기 위해 NAT Passthrough라는 것을 제공하며 UDP프로토콜에 ESP를 담아서 보내도록 구현이 된다. 이 문제는 이를 설정함으로써 해결 된다.

준비물은 MITM(Man in the middle attack)방지를 위한 서버 인증을 위한 인증서가 필요하다. 이 글에서는 self-signed 인증서를 사용하여 IKEv2서버 구축하는 방법을 알려주지 않는다. 만약 self-signed 인증서를 사용하게 되면 클라이언트에서 추가적인 설정이 필요할 수도 있다.

이 글은 공유기의 IP주소로 DNS/DDNS 등의 방법으로 도메인이 할당되어 있으며, 이 도메인으로 정상적인 SSL 인증서를 발급받았다는 전제로 작성되어 있다.

SSL 인증서는 일반적으로 유료이지만 StartSSL이나 Let’s Encrypt 등을 통하여 무료로 발급 가능하다.

IKEv2를 동작시키기 위해서는 UDP/500과 UDP/4500을 열어 두어야 한다. UDP/500은 IKE프로토콜을 위해 필요하며, UDP/4500은 IPSec을 이용하기위해 필요하다. 이 두가지 포트를 공유기에서 포트포워딩 설정을 해두어야 한다.

IKEv2를 사용하기 위해서는 strongswan이라는 패키지 설치와 암호화 기능 등의 기능을 사용하기 위해다.

1. 패키지 설치
apt-get install strongswan libcharon-extra-plugins

2. 인증서 설정

2.1. root 인증서 복사
발급받은 인증서의 루트 인증서 및 채인 인증서 복사
복사시 한 파일당 하나의 인증서만 포함 시킬 것
/etc/ipsec.d/cacerts

2.2. 인증서 복사
발급받은 인증서 파일 복사(pem)
/etc/ipsec.d/certs

2.3 인증서의 비밀키 복사
발급받을 때 사용한 인증서 비밀키 복사 (키 패스워드 제거할 것)
/etc/ipsec.d/private

2.4 권한 설정
chmod 740 /etc/ipsec.d/cacerts
chmod 740 /etc/ipsec.d/certs
chmod 700 /etc/ipsec.d/private

3. /etc/ipsec.conf 파일 수정

config setup
  strictcrlpolicy=yes
  uniqueids = no

conn roadwarrior
  auto=add
  compress=no
  type=tunnel     # tunnel: network 계층(ip)부터 암호화, transport: 전송 계층(transport layer; TCP/UDP)부터 암호화
  keyexchange=ikev2
  rekey=no
  reauth=no
  fragmentation=yes
  forceencaps=yes
  dpdaction=clear
  dpddelay=35s
  dpdtimeout=2000s
  left=%any
  leftid=@example.com   # 아래 ipsec.secrets의 이름과 통일, 인증서에 도메인 포함되어 있을 것
  leftcert=example_com.pem   # 상기 certs 디렉토리에 복사한 인증서 파일명으로 변경 
  leftsendcert=always
  leftsubnet=0.0.0.0/0
  leftauth=pubkey
  right=%any
  rightid=%any
  rightauth=eap-mschapv2
  eap_identity=%identity
  rightdns=192.168.1.1           # 여기서 rightdns 의 주소를 VPN사용시 쓸 DNS서버 주소로 변경 필요하다. (예: 8.8.8.8)
  rightsourceip=10.8.10.0/24
  rightsendcert=never

4. /etc/ipsec.secrets

# 서버 도메인과 키 설정

# 예제 - 아래 도메인은 클라이언트 설정시 사용, 인증서에 아래 도메인이 포함되어 있어야 함, 상기 복사한 비밀키 파일명을 사용함
example.com : RSA “example_com.key"

{{VPN접속ID}} : EAP “{{VPN접속PASSWORD}}"
# 예제
admin : EAP “password"

5. 서버 재시작
ipsec restart

6. 공유기(NAT) 포트 포워딩
UDP 500 과 UDP 4500을 내부에 설치된 VPN서버로 포워딩

7. 테스트
iOS기기나 macOS에서 아래의 설정으로 만듦
내부망과 외부망에서 각각 수행하여 정상적으로 접속 되는지 확인한다.

  • VPN Type : IKEv2
  • Server Address(서버 주소) : VPN의 도메인 주소 (예: example.com)
  • Remote ID (리모트 ID) : 상기 적은 도메인 주소(예: example.com)
  • Local ID (로컬 ID) : 비워둘 것
  • Authentication Settings…(인증 설정) : 사용자 이름
    사용자 이름 : ipsec.secrets 에 설정한 아이디
    패스워드 : ipsec.secrets 에 설정한 패스워드
VPN 설정 예시

VPN 설정 예시

 

connected to VPN

VPN 접속 성공

8. 관련 접속 로그 확인
tail -f /var/log/syslog
tail -f /var/log/auth.log

이 글을 통해 우분투 서버에서 IKEv2를 사용한 서버 구축이 가능하였으며 이를 통해 어디에서나 모바일 디바이스, 데스크톱을 통하여 내부 네트워크에 접속할 수 있게 되었으며, 암호화가 되어 안전한 환경에서 내부서버의 데이터를 사용할 수 있게 되었다.

참고문헌

[1] B. Schneier, Mudge, “Cryptanalysis of Microsoft’s PPTP Authentication Extensions (MS-CHAPv2)”, CQRE ’99, Springer-Verlag, 1999, pp. 192-203.
[2] “Prepare for removal of PPTP VPN before you upgrade to iOS 10 and macOS Sierra”, Apple, https://support.apple.com/en-us/HT206844
[3]  https://hide.me/en/blog/2015/03/whats-the-difference-considering-pptp-vs-l2tp-vs-sstp-vs-ikev2/
[4] https://hub.zhovner.com/geek/universal-ikev2-server-configuration/

9월 102016
 

우리는 ubuntu에서 패키지 인덱스를 업데이트 하기 위해 apt-get update 라는 명령을 사용하여 업데이트한다. 하지만 만약 커스텀 패키지를 이용하는 경우 (예: owncloud)에 keyexpired라는 문구를 볼 수 있다. 이는 패키지를 서명하는데 사용된 인증키가 시간이 지나 만료되었기 때문이다. 따라서 키를 다시 업데이트 해주는 작업이 필요하다. 아래의 절차를 따라 새로 받아보도록 하자.

1)  아래와 같은 메시지를  apt-get update 사용시 발견

Reading package lists... Done
W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: http://download.opensuse.org  Release: The following signatures were invalid: KEYEXPIRED 1472205884

W: Failed to fetch http://download.opensuse.org/repositories/isv:/ownCloud:/community/xUbuntu_14.04/Release

W: Some index files failed to download. They have been ignored, or old ones used instead.

2) apt-key list 명령어를 통해 expired 키를 찾기

# apt-key list | grep "expired:"
pub 1024D/BA684223 2012-02-08 [expired: 2016-08-26]

3) 목록에 있는 내용을 통해 “BA684223″이란 키가 2016-08-26에 만료되었으며 업데이트 해야함을 확인 가능

4) apt-key 명령으로 새로 키(BA684223)를 업데이트 받음

# apt-key adv --recv-keys --keyserver keys.gnupg.net BA684223

# apt-key adv --recv-keys --keyserver keys.gnupg.net BA684223
Executing: gpg --ignore-time-conflict --no-options --no-default-keyring --homedir /tmp/tmp.DE4JfiHL45 --no-auto-check-trustdb --trust-model always --keyring /etc/apt/trusted.gpg --primary-keyring /etc/apt/trusted.gpg --keyring /etc/apt/trusted.gpg.d/apt.postgresql.org.gpg --keyring /etc/apt/trusted.gpg.d/docker-maint-testing.gpg --keyring /etc/apt/trusted.gpg.d/openjdk-r-ppa.gpg --keyring /etc/apt/trusted.gpg.d/webupd8team-java.gpg --recv-keys --keyserver keys.gnupg.net BA684223
gpg: requesting key BA684223 from hkp server keys.gnupg.net
gpg: key BA684223: "isv:ownCloud OBS Project <isv:ownCloud@build.opensuse.org>" 5 new signatures
gpg: Total number processed: 1
gpg:         new signatures: 5

5) 다시 우분투 패키지 업데이트 작업을 진행한다.

# apt-get update

# apt-get upgrade

 

참고 자료

[1] http://superuser.com/questions/513609/how-to-apt-update-when-apt-is-not-accepting-the-repository