Strongswan ipsec VPN site to site 연결

OpenWrt 라우터간 strongwan을 이용해 site to site vpn연결하는 설정입니다. 먼저 간단하게 사전공유키(preshared key) 를 이용한 연결과 뒤이어 인증서(certificate) 생성해 연결하는 방법을 소개합니다.

참고로 strongswan 설정은 /etc/ipsec.conf 화일을 이용하는 방법과 /etc/swanctl/swanctl.conf 를 이용하는 방법이 있는데 지금 소개하는 방법은 예전방식 /etc/ipsec.conf를 이용하는 방법입니다.(둘의 차이는 설정화일 형식만 다를뿐 다른 차이는 없습니다.)

사이트정보

  • routerAAA
    • external IP : 57.57.57.57
    • internal IP : 10.10.10.0/24
    • hostname(ddns) : aaa.duckdns.org
  • routerBBB
    • external IP : 61.61.61.61
    • internal IP : 192.168.1.0/24
    • hostname(ddns) : bbb.duckdns.org

공통 준비

routerAAA, routerBBB 공통으로 설치 및 설정합니다.(기존에 roadwarrior 연결 설정으로 strongswan을 설치했다면 다음으로 건너뛰세요.)

사전준비

strongswan 패키지 및 dnsmasq-full 설치

opkg update
opkg install curl strongswan-default strongswan-pki ipset strongswan-mod-openssl strongswan-mod-curl strongswan-mod-dhcp strongswan-mod-eap-tls strongswan-mod-eap-identity strongswan-mod-kernel-libipsec kmod-tun openssl-util strongswan-mod-test-vectors strongswan-mod-farp

opkg install dnsmasq-full --download-only && opkg remove dnsmasq && opkg install dnsmasq-full --cache . && rm *.ipk

network 인터페이스 정의

ipsec 인터페이스 정의를 위해 /etc/config/network에 다음을 추가합니다.

...
config interface 'ipsec0'
        option ifname 'ipsec0'
        option proto 'none'
        option defaultroute '0'
        option peerdns '0'
        option ipv6 '0'

방화벽 규칙 추가

방화벽에 ipsec 연결 허용 규칙을 편집 추가를 위해 /etc/config/firewall을 수정합니다.

...
config rule
        option name 'Allow-IPSec-ESP'
        option src 'wan'
        option proto 'esp'
        option target 'ACCEPT'
config rule
        option name 'Allow-ISAKMP'
        option src 'wan'
        option dest_port '500'
        option proto 'udp'
        option target 'ACCEPT'
config rule
        option name 'IPSec-NAT-Traversal'
        option src 'wan'
        option proto 'udp'
        option dest_port '4500'
        option target 'ACCEPT'
config rule
        option name 'IPSec-Auth-Header'
        option src 'wan'
        option proto 'ah'
        option target 'ACCEPT'

Preshared key tunnel

routerAAA 설정

routerAAA, routerBBB에 사용될 사전 공유키(preshared key)를 준비합니다. 원하는 텍스트 문자로 지정할 수 있고 아래와 같이 openssl 명령으로 랜덤으로 생성할 수 있습니다.

openssl rand -base64 32

[email protected]:~# openssl rand -base64 32
yvXQ+uxaFAN4efHqWLy5WwFvrOJEEKJ0KHUTvx0Hq5U=

생성된 preshared key를 /etc/ipsec.secret 에 넣어줍니다.

형식은 id : PSK "preshared key" 이며 id는 ip, FQDN, [email protected], %any 가 될 수 있습니다. 여기서는 routerBBB의 FQDN을 넣었습니다.

# /etc/ipsec.secrets - strongSwan IPsec secrets file

bbb.duckdns.org : PSK yvXQ+uxaFAN4efHqWLy5WwFvrOJEEKJ0KHUTvx0Hq5U=

include /var/ipsec/ipsec.secrets

/etc/ipsec.conf 내용입니다.

[email protected]:~# cat /etc/ipsec.conf
# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
        strictcrlpolicy=no
        uniqueid=no

# Add connections here.

conn %default
        compress=no
        type=tunnel
        keyexchange=ikev2
        fragmentation=yes
        forceencaps=yes
        mobike=no

        dpdaction=clear
        dpddelay=300s
        rekey=no

conn s2s-psk
        auto=add
        authby=secret

        left=%any
        [email protected]
        leftsubnet=10.10.10.0/24
        leftfirewall=yes

        right=bbb.duckdns.org
        [email protected]
        rightsubnet=192.168.1.0/24

routerBBB 설정

routeAAA에서 생성한 preshared key를 /etc/ipsec.secret에 동일하게 넣어줍니다. id는 routerAAA를 지정합니다.

[email protected]:~# cat /etc/ipsec.secrets
# /etc/ipsec.secrets - strongSwan IPsec secrets file

aaa.duckdns.org : PSK yvXQ+uxaFAN4efHqWLy5WwFvrOJEEKJ0KHUTvx0Hq5U=

include /var/ipsec/ipsec.secrets

routeBBB의 /etc/ipsec.conf 내용입니다.

[email protected]:~# cat /etc/ipsec.conf
# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
        strictcrlpolicy=no
        uniqueid=no

# Add connections here.

conn %default
        compress=no
        type=tunnel
        keyexchange=ikev2
        fragmentation=yes
        forceencaps=yes
        mobike=no

        dpdaction=clear
        dpddelay=300s
        rekey=no

conn s2s-psk
        authby=secret

        left=%any
        [email protected]
        leftsubnet=192.168.1.0/24
        leftfirewall=yes

        right=aaa.duckdns.org
        [email protected]
        rightsubnet=10.10.10.0/24

서비스 재시작

routerAAA, routerBBB에서 각각 위에서 수정한것일 반연되도록 network, firewall, ipsec을 재시작 합니다.

/etc/init.d/network restart
/etc/init.d/firewall restart
/etc/init.d/ipsec restart

vpn 연결 및 확인

routerA, 또는 routerB에서 ipsec 연결 및 확인을 합니다.

ipsec up s2s-psk
ipsec status
ping 192.168.1.1

[email protected]:~# ipsec up s2s-psk
initiating IKE_SA s2s-psk[3] to 61.61.61.61
generating IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(FRAG_SUP) N(HASH_ALG) N(REDIR_SUP) ]
sending packet: from 57.57.57.57[500] to 61.61.61.61[500] (296 bytes)
received packet: from 61.61.61.61[500] to 57.57.57.57[500] (329 bytes)
parsed IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) CERTREQ N(FRAG_SUP) N(HASH_ALG) N(CHDLESS_SUP) N(MULT_AUTH) ]
selected proposal: IKE:AES_GCM_16_256/PRF_HMAC_SHA2_384/ECP_384
remote host is behind NAT
received 1 cert requests for an unknown ca
sending cert request for "C=KR, O=qquack, CN=qquack Root CA"
authentication of 'aaa.duckdns.org' (myself) with pre-shared key
establishing CHILD_SA s2s-psk{1}
generating IKE_AUTH request 1 [ IDi N(INIT_CONTACT) CERTREQ IDr AUTH SA TSi TSr N(MOBIKE_SUP) N(ADD_4_ADDR) N(ADD_4_ADDR) N(ADD_6_ADDR) N(MULT_AUTH) N(EAP_ONLY) N(MSG_ID_SYN_SUP) ]
sending packet: from 57.57.57.57[4500] to 61.61.61.61[4500] (362 bytes)
received packet: from 61.61.61.61[4500] to 57.57.57.57[4500] (255 bytes)
parsed IKE_AUTH response 1 [ IDr AUTH SA TSi TSr N(MOBIKE_SUP) N(ADD_4_ADDR) N(ADD_4_ADDR) ]
authentication of 'bbb.duckdns.org' with pre-shared key successful
IKE_SA s2s-psk[3] established between 57.57.57.57[aaa.duckdns.org]...61.61.61.61[bbb.duckdns.org]
selected proposal: ESP:AES_GCM_16_256/NO_EXT_SEQ
CHILD_SA s2s-psk{1} established with SPIs 229889cf_i 9eb3bb18_o and TS 10.10.10.0/24 === 192.168.1.0/24
connection 's2s-psk' established successfully
[email protected]:~#
[email protected]:~#
[email protected]:~# ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes
64 bytes from 192.168.1.1: seq=0 ttl=64 time=9.895 ms
64 bytes from 192.168.1.1: seq=1 ttl=64 time=12.800 ms
64 bytes from 192.168.1.1: seq=2 ttl=64 time=11.828 ms
64 bytes from 192.168.1.1: seq=3 ttl=64 time=9.953 ms
^C
--- 192.168.1.1 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 9.895/11.119/12.800 ms
[email protected]:~#

Certificates tunnel

인증서 생성

인증서 생성작업은 routerAAA에서 진행하며, 인증서 생성을 위한 쉘스크립트를 /etc/ipsec.d 에 만듭니다.

(지난번에는 인증서 확장자가 pem(텍스트화일)이 아닌 der(2진화일)였는데 인증서 확장자가 pem이든 der든 상관없습니다. 2진화일이 기계한테는 빠를지 몰라도 이용자에게는 텍스트가 사용하기 편해서 pem으로 바꿨습니다.)

  • mk_rsa_ca.sh : Root CA 인증서 생성 스크립트(한번만 실행하세요. 다시 실행하면 기존에 생성한 서버/사용자 인증서가 모두 무력화 됩니다.)
  • mk_rsa_server.sh : 서버 인증서 생성 스크립트
  • mk_rsa_user.sh : 사용자 인증서 생성 스크립트
  • clean.sh : /etc/ipsec.d/ 하위 디렉토리 모든 화일을 삭제(모든 인증서 생성을 다시 하고 싶을 때 모든 인증서 삭제)

cd /etc/ipsec.d
vi mk_rsa_ca.sh

#!/bin/sh

COUNTRY="KR"
ORG="qquack"

VALIDDAYS="3652"

ipsec pki --gen --type rsa --size 4096 --outform pem > private/cakey.pem
chmod 600 private/cakey.pem

ipsec pki --self --ca --lifetime $VALIDDAYS --in private/cakey.pem --type rsa --dn "C=$COUNTRY, O=$ORG, CN=$ORG Root CA" --outform pem > cacerts/cacert.pem
ipsec pki --print --in cacerts/cacert.pem

vi mk_rsa_server.sh

#!/bin/sh

SRVNAME="aaa.duckdns.org"

#Uncomment only if vpn server is behind a static IP
#IPADDR=$(. /lib/functions/network.sh; network_get_ipaddr ip wan; echo $ip)
#IPADDR="aaa.duckdns.org"

COUNTRY="KR"
ORG="qquack"

LIFETIME="3652"

ipsec pki --gen --type rsa --size 4096 --outform pem > private/hostkey.pem
chmod 600 private/hostkey.pem

ipsec pki --pub --in private/hostkey.pem --type rsa | ipsec pki --issue --lifetime $LIFETIME --cacert cacerts/cacert.pem --cakey private/cakey.pem --dn "C=$COUNTRY, O=$ORG, CN=$SRVNAME" --san $SRVNAME --flag serverAuth --flag ikeIntermediate --outform pem > certs/hostcert.pem
ipsec pki --print --in certs/hostcert.pem

vi mk_rsa_user.sh

#!/bin/sh

USERID="[email protected]"
NAME="user1"

#echo "Enter userid (no spaces or special characters):"
#read USERID
#
#[ -z "$USERID" ] && {
#       echo Empty user ID. Cancelling.
#       exit 0
#}
#
#echo "Enter fullname:"
#read NAME
#
#[ -z "$NAME" ] && {
#       echo Empty full name. Cancelling.
#       exit 0
#}

COUNTRY="KR"
ORG="qquack"

LIFETIME="1826"

mkdir -p /etc/ipsec.d/p12 2> /dev/null

ipsec pki --gen --type rsa --size 4096 --outform pem > private/$USERID.pem
chmod 600 private/$USERID.pem

ipsec pki --pub --in private/$USERID.pem --type rsa | ipsec pki --issue --lifetime $LIFETIME --cacert cacerts/cacert.pem --cakey private/cakey.pem --dn "C=$COUNTRY, O=$ORG, CN=$USERID" --san "$USERID" --outform pem > certs/$USERID.pem
ipsec pki --print --in certs/$USERID.pem

openssl pkcs12 -export -inkey private/$USERID.pem -in certs/$USERID.pem -name "$NAME's VPN Certificate" -certfile cacerts/cacert.pem -caname "$ORG Root CA" -out p12/$USERID.p12

vi clean.sh

#!/bin/sh
rm /etc/ipsec.d/*/*.* 2> /dev/null

각각의 스크립트에 실행 권한을 주고 ca, server, user 인증서를 생성합니다.

chmod 700 *.sh | chmod 600 clean.sh
./mk_rsa_ca.sh
./mk_rsa_server.sh
./mk_rsa_user.sh

인증서 복사

routerAAA, routeBBB에 쓰일 인증서는 모두 routerAAA에서 생성되었기 때문에 scp를 이용해 routerBBB로 전송할 예정입니다.

먼저 routerBBB에 ssh로 로그인하여 패스워드(sshkey가 아닌 /etc/passwd)로 ssh를 통한 shell 접속이 가능하도록 /etc/config/dropbear 설정을 아래와 같이 uci 명령으로 바꿉니다.

uci set [email protected][-1].RootPasswordAuth="on"
uci set [email protected][-1].PasswordAuth="on"
uci commit dropbear
/etc/init.d/dropbear restart

routerAAA에서 scp를 이용해 routerBBB로 인증서 화일을 전송합니다. scp 명령 형식은 scp -P <port> file [email protected]:path 이며 아래 예에서 routerBBB의 ssh 서비스 포트는 2222 입니다. 포트번호는 확인하세요.

scp -P 2222 cacerts/cacrt.pem [email protected]:/etc/ipsec.d/cacerts/

scp -P 2222 certs/[email protected] [email protected]:/etc/ipsec.d/certs/

scp -P 2222 private/[email protected] [email protected]:/etc/ipsec.d/private/

인증서 전송이 완료되면 routerBBB의 ssh 로그인이 패스워드를 통한 접속이 불가하도록 원상복구 합니다.

uci set [email protected][-1].RootPasswordAuth="off"
uci set [email protected][-1].PasswordAuth="off"
uci commit dropbear
/etc/init.d/dropbear restart

routerAAA 설정

/etc/ipsec.secret 화일에 routerAAA의 private 인증서 화일의 위치를 넣어줍니다. 형식은 : RSA : privatekey

vi /etc/ipsec.secret

# /etc/ipsec.secrets - strongSwan IPsec secrets file
 : RSA /etc/ipsec.d/private/hostkey.pem
bbb.duckdns.org : PSK yvXQ+uxaFAN4efHqWLy5WwFvrOJEEKJ0KHUTvx0Hq5U=

include /var/ipsec/ipsec.secrets

vi /etc/ipsec.conf

...
conn s2s-cert
        auto=add

        left=%any
        leftid=%any
        leftsubnet=10.10.10.0/24
        leftcert=/etc/ipsec.d/certs/hostcert.pem
        leftfirewall=yes

        right=bbb.duckdns.org
        rightid="C=KR, O=qquack, [email protected]"
        rightsubnet=192.168.1.0/24

routerBBB 설정

vi /etc/ipsec.secret

# /etc/ipsec.secrets - strongSwan IPsec secrets file
 : RSA /etc/ipsec.d/private/[email protected]
aaa.duckdns.org : PSK yvXQ+uxaFAN4efHqWLy5WwFvrOJEEKJ0KHUTvx0Hq5U=

include /var/ipsec/ipsec.secrets

vi /etc/ipsec.conf

...
conn s2s-cert
        auto=add

        left=%any
        leftid=%any
        leftsubnet=192.168.1.0/24
        leftcert=/etc/ipsec.d/certs/[email protected]
        leftfirewall=yes

        right=aaa.duckdns.org
        rightid="C=KR, O=qquack, CN=aaa.duckdns.org"
        rightsubnet=10.10.10.0/24

서비스 재시작

routerAAA, routerBBB에서 각각 ipsec을 재시작 합니다.

/etc/init.d/ipsec restart

vpn 연결 및 확인

routerAAA 또는 routerBBB에서 ipsec 연결 및 확인을 합니다.

그리고 각각의 로컬 네트워크 하부의 PC에 ping을 날려보세요.(먼저 해당 PC 방화벽에서 해당 subnet을 개방하는것 잊지마세요.)

상대 네트워크 하부 PC에 핑이 날라가면 성공입니다.

ipsec up s2s-cert
ipsec status
ping 10.10.10.1
ping 10.10.10.191

[email protected]:/etc# uci show network.lan.ipaddr
network.lan.ipaddr='192.168.1.1'
[email protected]:/etc#
[email protected]:/etc# ipsec up s2s-cert
initiating IKE_SA s2s-cert[3] to 57.57.57.57
generating IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(FRAG_SUP) N(HASH_ALG) N(REDIR_SUP) ]
sending packet: from 61.61.61.61[500] to 57.57.57.57[500] (732 bytes)
received packet: from 57.57.57.57[500] to 61.61.61.61[500] (305 bytes)
parsed IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) CERTREQ N(FRAG_SUP) N(HASH_ALG) N(CHDLESS_SUP) N(MULT_AUTH) ]
selected proposal: IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256
remote host is behind NAT
received cert request for "C=KR, O=qquack, CN=qquack Root CA"
sending cert request for "C=KR, O=qquack, CN=qquack Root CA"
authentication of 'C=KR, O=qquack, [email protected]' (myself) with RSA_EMSA_PKCS1_SHA2_384 successful
sending end entity cert "C=KR, O=qquack, [email protected]"
establishing CHILD_SA s2s-cert{3}
generating IKE_AUTH request 1 [ IDi CERT N(INIT_CONTACT) CERTREQ IDr AUTH SA TSi TSr N(MULT_AUTH) N(EAP_ONLY) N(MSG_ID_SYN_SUP) ]
splitting IKE message (2320 bytes) into 2 fragments
generating IKE_AUTH request 1 [ EF(1/2) ]
generating IKE_AUTH request 1 [ EF(2/2) ]
sending packet: from 61.61.61.61[4500] to 57.57.57.57[4500] (1236 bytes)
sending packet: from 61.61.61.61[4500] to 57.57.57.57[4500] (1156 bytes)
received packet: from 57.57.57.57[4500] to 61.61.61.61[4500] (1236 bytes)
parsed IKE_AUTH response 1 [ EF(1/2) ]
received fragment #1 of 2, waiting for complete IKE message
received packet: from 57.57.57.57[4500] to 61.61.61.61[4500] (980 bytes)
parsed IKE_AUTH response 1 [ EF(2/2) ]
received fragment #2 of 2, reassembled fragmented IKE message (2144 bytes)
parsed IKE_AUTH response 1 [ IDr CERT AUTH SA TSi TSr ]
received end entity cert "C=KR, O=qquack, CN=aaa.duckdns.org"
  using certificate "C=KR, O=qquack, CN=aaa.duckdns.org"
  using trusted ca certificate "C=KR, O=qquack, CN=qquack Root CA"
checking certificate status of "C=KR, O=qquack, CN=aaa.duckdns.org"
certificate status is not available
  reached self-signed root ca with a path length of 0
authentication of 'C=KR, O=qquack, CN=aaa.duckdns.org' with RSA_EMSA_PKCS1_SHA2_384 successful
IKE_SA s2s-cert[3] established between 61.61.61.61[C=KR, O=qquack, [email protected]]...57.57.57.57[C=KR, O=qquack, CN=aaa.duckdns.org]
selected proposal: ESP:AES_CBC_128/HMAC_SHA2_256_128/NO_EXT_SEQ
CHILD_SA s2s-cert{3} established with SPIs fc87343c_i e450cb5d_o and TS 192.168.1.0/24 === 10.1.1.0/24
connection 's2s-cert' established successfully
[email protected]:/etc#
[email protected]:/etc#
[email protected]:/etc#
[email protected]:/etc# ipsec status
Security Associations (1 up, 0 connecting):
    s2s-cert[3]: ESTABLISHED 15 seconds ago, 61.61.61.61[C=KR, O=qquack, [email protected]]...57.57.57.57[C=KR, O=qquack, CN=aaa.duckdns.org]
    s2s-cert{3}:  INSTALLED, TUNNEL, reqid 3, ESP in UDP SPIs: fc87343c_i e450cb5d_o
    s2s-cert{3}:   192.168.1.0/24 === 10.1.1.0/24
[email protected]:/etc#
[email protected]:/etc#
[email protected]:/etc# ping 10.10.10.1
PING 10.10.10.1 (10.10.10.1): 56 data bytes
64 bytes from 10.10.10.1: seq=0 ttl=64 time=11.241 ms
64 bytes from 10.10.10.1: seq=1 ttl=64 time=9.976 ms
64 bytes from 10.10.10.1: seq=2 ttl=64 time=12.410 ms
64 bytes from 10.10.10.1: seq=3 ttl=64 time=11.503 ms
64 bytes from 10.10.10.1: seq=4 ttl=64 time=12.517 ms
^C
--- 10.10.10.1 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max = 9.976/11.529/12.517 ms
[email protected]:/etc#
[email protected]:/etc#
[email protected]:/etc#
[email protected]:/etc# ping 10.10.10.191
PING 10.10.10.191 (10.10.10.191): 56 data bytes
64 bytes from 10.10.10.191: seq=0 ttl=127 time=11.824 ms
64 bytes from 10.10.10.191: seq=1 ttl=127 time=10.619 ms
64 bytes from 10.10.10.191: seq=2 ttl=127 time=10.639 ms
64 bytes from 10.10.10.191: seq=3 ttl=127 time=11.598 ms
^C
--- 10.10.10.191 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 10.619/11.170/11.824 ms
[email protected]:/etc#
[email protected]:/etc#

vpn 연결해제

ipsec down s2s-cert

참고사이트

감사를 표합니다

테스트를 위해 라우터를 사용할 수 있도록 배려해주신 @mabaha님께 감사를 표합니다.

Comments

No comments yet. Why don’t you start the discussion?

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다

5  ×  2  =