Strongswan IPSec vpn on CentOS7

오늘은 vpn에 대해서 정리 해볼까 합니다. 대중적으로 많이 사용하고 있는 공유기들 요즘 pptp 기반의 vpn 을 많이 사용했었는데, 최근들어 vpn 시장에서 pptp 를 퇴출할려는 움직임이 많이 보이고 있습니다. 올해 선보인 apple 소프트웨들도 vpn client 로 pptp 를 제거하고 IPSec, IKEv2, L2TP 만 지원하는 형태로 변경이 되었죠, IOS를 업그레이드 하면서 pptp가 없어져, VPN를 사용 못하게 되어 불편을 겪는분들이 좀 있을거 같네요. 아래의 설명은 strongswan 을 사용해서 IPSec기반의 VPN을 만들어 볼려고 합니다.

ipsec vpn

ipsec vpn diagram

통상 VPN 장비가 있을경우, 공유기를 대체 하여, NAT 기능을 활용 할수 있을것입니다. 이경우 VPN 장비에서 지원하는 방화벽 기능까지 모두 활성화 해서 사용할 수도 있을것입니다. 만약에 공유기를 꼭 사용해야 하고, VPN 장비 혹은 VPN 서버를 공유기 아래에 둘경우 위와 같은 구조로 구성이 될것이며, 공유기에서 Port Forward 기능을 사용해서 해당 VPN 포트를 VPN 서버 혹은 장비 쪽으로 전달 해줄 수 있도록 하면 됩니다.

IPSec VPN 사용 Port
Public IP : UDP 500 Port ---> Private VPN IP : UDP 500 Port
Public IP : UDP 4500 Port ---> Private VPN IP : UDP 4500 Port

VPN 관련 패키지 설치

yum install epel-release
yum install strongswan openssl

인증서 생성 스크립트 , 아래의 내용중에 O=ISBC 를 각자 원하는 조직 이름으로 변경 해서 사용 하면 됩니다.

## 서버 인증서 만드는 스크립트
[root@vpn ipsec.d]# cat server_key.sh 
#!/bin/bash
if [ $1 ];	then
	CN=$1
	echo "generating keys for $CN ..."
else
	echo "usage:\n sh server_key.sh YOUR EXACT HOST NAME or SERVER IP\n Run this script in directory to store your keys"
	exit 1
fi

mkdir -p private && mkdir -p cacerts && mkdir -p certs

strongswan pki --gen --type rsa --size 4096 --outform pem > private/strongswanKey.pem
strongswan pki --self --ca --lifetime 3650 --in private/strongswanKey.pem --type rsa --dn "C=CH, O=ISBC, CN=$CN" --outform pem > cacerts/strongswanCert.pem
echo 'CA certs at cacerts/strongswanCert.pem\n'
strongswan pki --print --in cacerts/strongswanCert.pem

sleep 1
echo "\ngenerating server keys ..."
strongswan pki --gen --type rsa --size 2048 --outform pem > private/vpnHostKey.pem
strongswan pki --pub --in private/vpnHostKey.pem --type rsa | \
	strongswan pki --issue --lifetime 730 \
	--cacert cacerts/strongswanCert.pem \
	--cakey private/strongswanKey.pem \
	--dn "C=CH, O=ISBC, CN=$CN" \
	--san $CN \
	--flag serverAuth --flag ikeIntermediate \
	--outform pem > certs/vpnHostCert.pem
echo "vpn server cert at certs/vpnHostCert.pem\n"
strongswan pki --print --in certs/vpnHostCert.pem

## 클라이언트 인증서 만드는 스크립트

[root@vpn ipsec.d]# cat client_key.sh 
#!/bin/bash
info="usage:\n sh client_key.sh USER_NAME EMAIL \n Run this script in directory to store your keys"
if [ $1 ];	then
	if [ $2 ]; then
		NAME=$1
		MAIL=$2
		echo "generating keys for $NAME $MAIL ..."
	else
		echo $info
		exit 1
	fi
else
	echo $info
	exit 1
fi
mkdir -p private && mkdir -p cacerts && mkdir -p certs
keyfile="private/"$NAME"Key.pem"
certfile="certs/"$NAME"Cert.pem"
p12file=$NAME".p12"
strongswan pki --gen --type rsa --size 2048 \
	--outform pem \
	> $keyfile
strongswan pki --pub --in $keyfile --type rsa | \
	strongswan pki --issue --lifetime 730 \
	--cacert cacerts/strongswanCert.pem \
	--cakey private/strongswanKey.pem \
	--dn "C=CH, O=ISBC, CN=$MAIL" \
	--san $MAIL \
	--outform pem > $certfile
strongswan pki --print --in $certfile
echo "\nEnter password to protect p12 cert for $NAME"
openssl pkcs12 -export -inkey $keyfile \
	-in $certfile -name "$NAME's VPN Certificate" \
	-certfile cacerts/strongswanCert.pem \
	-caname "strongSwan Root CA" \
	-out $p12file
if [ $? -eq 0 ]; then
	echo "cert for $NAME at $p12file"
fi

위의 스크립트를  /etc/strongswan/ipsec.d 에 생성하여 각 서버와 클라이언트 키를 생성 해줍니다.

# server_key.sh [VPN IP 혹은 DNS] 공유기를 사용할경우 공유기의 IP혹은 공유기의 DDNS 이름 사용
# client_key.sh [사용자ID] [사용자Email]
# find ./ | grep pem
./cacerts/strongswanCert.pem
./certs/vpnHostCert.pem
./certs/isbcCert.pem
./private/strongswanKey.pem
./private/vpnHostKey.pem
./private/isbcKey.pem
[root@vpn ipsec.d]# find ./ | grep p12
./isbc.p12

생성이 완료되면 위와같은 파일들이 생성된것을 볼 수 있습니다. 다음으로 ipsec.conf 의 내용을 아래와 같이 정리 해줍니다. 내용중에 IP 부문의 xxx 만 수정해서 사용 하면 됩니다. IP 할당 범위를 지정해주는것입니다. 공유기에서  사용하지 않는 IP 범위를 지정 해주면 됩니다. DNS는 google dns 를 사용 하였습니다.

# cat ipsec.conf
config setup
    uniqueids=never
    charondebug="cfg 0 , ike 0 , net 0 , knl 0 , esp 0 , dmn 0 , mgr 0 , job 0"

conn %default
    keyexchange=ikev1
    ike=aes128-sha256-ecp256,aes256-sha384-ecp384,aes128-sha256-modp2048,aes128-sha1-modp2048,aes256-sha384-modp4096,aes256-sha256-modp4096,aes256-sha1-modp4096,aes128-sha256-modp1536,aes128-sha1-modp1536,aes256-sha384-modp2048,aes256-sha256-modp2048,aes256-sha1-modp2048,aes128-sha256-modp1024,aes128-sha1-modp1024,aes256-sha384-modp1536,aes256-sha256-modp1536,aes256-sha1-modp1536,aes256-sha384-modp1024,aes256-sha256-modp1024,aes256-sha1-modp1024!
    esp=aes128gcm16-ecp256,aes256gcm16-ecp384,aes128-sha256-ecp256,aes256-sha384-ecp384,aes128-sha256-modp2048,aes128-sha1-modp2048,aes256-sha384-modp4096,aes256-sha256-modp4096,aes256-sha1-modp4096,aes128-sha256-modp1536,aes128-sha1-modp1536,aes256-sha384-modp2048,aes256-sha256-modp2048,aes256-sha1-modp2048,aes128-sha256-modp1024,aes128-sha1-modp1024,aes256-sha384-modp1536,aes256-sha256-modp1536,aes256-sha1-modp1536,aes256-sha384-modp1024,aes256-sha256-modp1024,aes256-sha1-modp1024,aes128gcm16,aes256gcm16,aes128-sha256,aes128-sha1,aes256-sha384,aes256-sha256,aes256-sha1!
    dpdaction=clear
    dpddelay=300s
    rekey=no
    left=%defaultroute
    leftsubnet=0.0.0.0/0
    leftcert=vpnHostCert.pem
    right=%any
    rightdns=8.8.8.8,8.8.4.4
    rightsourceip=xxx.xxx.xx.80-xxx.xxx.xxx.100

conn CiscoIPSec
    keyexchange=ikev1
    forceencaps=yes
    authby=xauthpsk
    xauth=server
    fragmentation=yes
    rightauth=psk
    rightauth2=xauth
    leftsendcert=always
    rekey=no
    auto=add

conn XauthPsk
    keyexchange=ikev1
    leftauth=psk
    rightauth=psk
    rightauth2=xauth
    auto=add

conn IpsecIKEv2
    keyexchange=ikev2
    leftauth=pubkey
    rightauth=pubkey
    leftsendcert=always
    auto=add

conn IpsecIKEv2-EAP
    keyexchange=ikev2
    ike=aes256-sha1-modp1024!
    rekey=no
    leftauth=pubkey
    leftsendcert=always
    rightauth=eap-mschapv2
    eap_identity=%any
    auto=add

conn ios
    keyexchange=ikev1
    authby=xauthpsk
    xauth=server
    left=%defaultroute
    leftsubnet=0.0.0.0/0
    leftfirewall=yes
    right=%any
    rightsubnet=xxx.xxx.xxx.0/24
    rightsourceip=xxx.xxx.xxx.80-xxx.xxx.xxx.100
    rightdns=8.8.8.8
    auto=add

이어서 strongswan.conf 를 아래와 같이 수정 합니다.

# cat strongswan.conf 
# strongswan.conf - strongSwan configuration file
#
# Refer to the strongswan.conf(5) manpage for details
#
# Configuration changes should be made in the included files

charon {
	load_modular = yes
	duplicheck.enable = no
	compress = yes
	plugins {
		include strongswan.d/charon/*.conf
	}
    dns1 = 8.8.8.8
    dns2 = 8.8.4.4
    nbns1 = 8.8.8.8
    nbns2 = 8.8.4.4
}

include strongswan.d/*.conf

VPN 사용자 ID 에 따른 비밀번호를 설정 합니다. 위에 client_key.sh 에서 사용자 id 추가 지정할때 정의하는 비밀번호를 사용하여 아래에 text 로 그대로 입력.

# cat ipsec.secrets 
include /etc/ipsec.d/*.secrets

%any %any : RSA vpnHostKey.pem
%any %any : PSK "비밀번호 설정"  #VPN Client 에서 비밀글 입력 하는 부분에 넣어주는 키 입니다.
isbc %any : EAP "사용자 비밀번호" #EAP 와 XAUTH의 비밀번호 동일하게 설정
isbc %any : XAUTH "사용자 비밀번호" #맨위에 client_key.sh 에서 입력한 동일한 password 지정

/etc/strongswan/ipsec.secrets 파일을  /etc 에 링크 걸어주고 난후에,  /etc/sysctl.conf 를 아래와 같이 수정

# cat /etc/sysctl.conf 
# System default settings live in /usr/lib/sysctl.d/00-system.conf.
# To override those settings, enter new settings here, or in an /etc/sysctl.d/.conf file
#
# For more information, see sysctl.conf(5) and sysctl.d(5).
net.ipv4.ip_forward=1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0

수정 후
# sysctl -p

방화벽 룰 추가 설정

# firewall-cmd --permanent --add-service="ipsec"
# firewall-cmd --permanent --add-port=4500/udp
# firewall-cmd --permanent --add-port=500/udp
# firewall-cmd --permanent --add-masquerade
# firewall-cmd --reload

# firewall-cmd --list-all
public (default, active)
  interfaces: eth0
  sources: 
  services: dhcpv6-client ipsec ssh
  ports: 500/udp 4500/udp 68/udp
  masquerade: yes
  forward-ports: 
  icmp-blocks: 
  rich rules: 

모든 설정이 마무리 되면 서비스 시작,  아래의 command 참고 하면 된다.

# systemctl enable strongswan
# systemctl start strongswan
# strongswan restart
# strongswan status
Security Associations (1 up, 0 connecting):
    XauthPsk[12]: ESTABLISHED 3 seconds ago, (내부 VPN 서버 사설IP) xxx.xxx.xxx.xxx[C=CH, O=ISBC, CN=wans.iptime.org]...(VPN Client 의 공인 IP)xxx.xxx.xxx.xxx[(VPN Client의 사설 IP)xxx.xxx.xxx.xxx]
    XauthPsk{12}:  INSTALLED, TUNNEL, reqid 12, ESP in UDP SPIs: c72f7e16_i 0a380105_o
    XauthPsk{12}:   0.0.0.0/0 === (내부 VPN 접속후 할당 받은 IP) xxx.xxx.xxx.81/32

이렇게 하여, MacBook , IOS 등 최신의 OS 환경에서 IPSec 을 사용한 VPN 환경을 만들어 보았습니다. VPN Client Device 에서 접속하면, 아래와 같은 형태의 messages log 를 볼수 있습니다.

Sep 26 00:17:11 vpn charon: 05[ENC] parsed ID_PROT request 0 [ SA V V V V V V V V V V V V V V ]
Sep 26 00:17:11 vpn charon: 05[IKE] 223.33.165.36 is initiating a Main Mode IKE_SA
Sep 26 00:17:11 vpn charon: 05[ENC] generating ID_PROT response 0 [ SA V V V V ]
Sep 26 00:17:11 vpn charon: 05[ENC] parsed ID_PROT request 0 [ KE No NAT-D NAT-D ]
Sep 26 00:17:11 vpn charon: 05[ENC] generating ID_PROT response 0 [ KE No NAT-D NAT-D ]
Sep 26 00:17:11 vpn charon: 02[ENC] parsed ID_PROT request 0 [ ID HASH N(INITIAL_CONTACT) ]
Sep 26 00:17:11 vpn charon: 02[ENC] generating ID_PROT response 0 [ ID HASH ]
Sep 26 00:17:11 vpn charon: 02[ENC] generating TRANSACTION request 527936815 [ HASH CPRQ(X_USER X_PWD) ]
Sep 26 00:17:11 vpn charon: 05[ENC] parsed TRANSACTION response 527936815 [ HASH CPRP(X_USER X_PWD) ]
Sep 26 00:17:11 vpn charon: 05[ENC] generating TRANSACTION request 3198576801 [ HASH CPS(X_STATUS) ]
Sep 26 00:17:12 vpn charon: 15[ENC] parsed TRANSACTION response 3198576801 [ HASH CPA(X_STATUS) ]
Sep 26 00:17:12 vpn charon: 15[IKE] IKE_SA XauthPsk[14] established between xxx.xxx.xxx.xxx[C=CH, O=ISBC, CN=xxx.xxx.org]...xxx.xxx.xxx.xxx[xxx.xxx.xxx.xxx]
Sep 26 00:17:12 vpn charon: 16[ENC] unknown attribute type (28683)
Sep 26 00:17:12 vpn charon: 16[ENC] parsed TRANSACTION request 648710076 [ HASH CPRQ(ADDR MASK DNS NBNS EXP VER U_BANNER U_DEFDOM U_SPLITDNS U_SPLITINC U_LOCALLAN U_PFS U_SAVEPWD U_FWTYPE U_BKPSRV (28683)) ]
Sep 26 00:17:12 vpn charon: 16[ENC] generating TRANSACTION response 648710076 [ HASH CPRP(ADDR DNS NBNS DNS NBNS DNS DNS) ]
Sep 26 00:17:12 vpn charon: 04[ENC] parsed QUICK_MODE request 860013045 [ HASH SA No ID ID ]
Sep 26 00:17:12 vpn charon: 04[ENC] generating QUICK_MODE response 860013045 [ HASH SA No ID ID ]
Sep 26 00:17:12 vpn charon: 03[ENC] parsed QUICK_MODE request 860013045 [ HASH ]
Sep 26 00:17:12 vpn charon: 03[IKE] CHILD_SA XauthPsk{14} established with SPIs c83523d1_i 012f9f46_o and TS 0.0.0.0/0 === xxx.xxx.xxx.81/32

strongswan 을 사용하면, 기존에 Linux 기반의 NAS 가 있거나, RaspberryPi2 가 있다면, 각 환경에 맞게 구성해서 사용 할수 있을것입니다. VM으로 하나 만들어서 Test 해보니, VPN 서버에 접속해서 NAS에 있는 데이터 접근 속도가 기존 공유기에서 PPTP로 서비스 할때보다  좀더 빠른거 같은 느낌이있네요~

Reference Site

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다