OpenWrt strongswan 으로 구성한 ikev2 vpn

사전준비

  • 설치에 앞서 vpn firewall 정책설정이 선행되어야 합니다.
  • ddns 설정을 하지 않았다면 ddns설정을 참고하세요. (아래 예시는 myhost.duckdns.org를 사용합니다.)

설치구성

  • 클라이언트 인증은 인증서 기반 (pubkey 및 eap-tls)
  • 클라이언트는 라우터와 같은 네트워크인 192.168.1.0/24 사용하며 dhcp로 자동할당
  • 클라이언트의 dns는 서버(OpenWrt 라우터)의 dns 사용 (DoT로 구성한 192.168.1.1)

strongswan 설치

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

dhcp 구성을 위한 dnsmasq-full 설치 (기존 dnsmasq는 삭제)

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

인증서 생성

인증서 작업을 위한 쉘스크립트를 만들고 실행해 인증서를 만듭니다.

  • mk_server.sh : 루트와 서버인증서 생성 스크립트(한번만 실행하세요. 다시 실행하면 다른 인증서가 생성되어 클라이언트와 인증서가 일치하지 않게됩니다.)
  • mk_client.sh : 클라이언트 인증서 생성 스크립트

cd /etc/ipsec.d
touch mk_server.sh
vi mk_server.sh

#!/bin/sh

SRVNAME="OpenWrt"
IPADDR="myhost.duckdns.org"

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

COUNTRY="KR"
ORG="OpenWrt"
#Change above to your org and country code

VALIDDAYS="3650"
LIFETIME="3650"

ipsec pki --gen --type rsa --size 2048 --outform der > private/cakey.der
chmod 600 private/cakey.der

ipsec pki --self --ca --lifetime $VALIDDAYS --in private/cakey.der --type rsa --dn "C=$COUNTRY, O=$ORG, CN=$ORG Root CA" --outform der > cacerts/cacrt.der
openssl x509 -inform DER -in cacerts/cacrt.der -out cacerts/cacrt.pem -outform PEM

ipsec pki --print --in cacerts/cacrt.der

ipsec pki --gen --type rsa --size 2048 --outform der > private/hostkey.der
chmod 600 private/hostkey.der

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

touch mk_client.sh
vi mk_client.sh

#!/bin/sh

COUNTRY="KR"
ORG="OpenWrt"

LIFETIME="1825"

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

#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
#}

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

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

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

openssl x509 -inform DER -in certs/$USERID.der -out certs/$USERID.pem -outform PEM
openssl pkcs12 -export -inkey private/$USERID.pem -in certs/$USERID.pem -name "$NAME's VPN Certificate" -certfile cacerts/cacrt.pem -caname "$ORG Root CA" -out p12/$USERID.p12

chmod 700 *.sh
./mk_server.sh
./mk_client.sh

ipsec 인터페이스 정의

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'

/etc/firewall.user에 추가합니다.

iptables -I INPUT   -m policy --dir in  --pol ipsec --proto esp -j ACCEPT
iptables -I FORWARD -m policy --dir in  --pol ipsec --proto esp -j ACCEPT
iptables -I FORWARD -m policy --dir out --pol ipsec --proto esp -j ACCEPT
iptables -I OUTPUT  -m policy --dir out --pol ipsec --proto esp -j ACCEPT
iptables -t nat -I POSTROUTING -m policy --pol ipsec --dir out -j ACCEPT

ipsec 구성화일

/etc/ipsec.conf 화일을 다음과 같이 수정합니다. 클라이언트 인증은 인증서 기반 (pubkey 및 eap-tls)으로 구성

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
        charondebug="ike 1, knl 1, cfg 0"
        strictcrlpolicy=no
        uniqueid=no

# Add connections here.

conn %default
        auto=add
        compress=no
        type=tunnel
        keyexchange=ikev2
        fragmentation=yes
        forceencaps=no
        authby=pubkey
        mobike=yes

        dpdaction=clear
        dpddelay=300s
        rekey=no

        left=%any
        [email protected]
        leftcert=/etc/ipsec.d/certs/hostcrt.der
        leftsendcert=always
        leftsubnet=0.0.0.0/0

        right=%any
        rightid=%any
        rightsourceip=%dhcp
        rightdns=192.168.1.1
        rightsendcert=never

        eap_identity=%identity

conn rw-eaptls
        rightauth=eap-tls

conn rw-pub
        rightauth=pubkey

conn rw-eaptls-ios
        rightid=SHAREDSAN
        rightauth=eap-tls

conn rw-pub-ios
        rightid=SHAREDSAN
        rightauth=pubkey

ipsec.secrets

/etc/ipsec.secrets 화일을 다음과 같이 수정합니다.

# /etc/ipsec.secrets - strongSwan IPsec secrets file
: RSA /etc/ipsec.d/private/hostkey.der

strongswan 구성화일

/etc/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
        dns1 = 192.168.1.1
        plugins {
                include strongswan.d/charon/*.conf
        dhcp {
                        force_server_address = yes
                        # use_server_port = yes
                        # uncomment the line above if log shows that DHCP
                        # offer can't be accepted
                        identity_lease = yes
                        server = 192.168.1.255
                        # use LAN broadcast address here, not IP address.
                }
        }
}

include strongswan.d/*.conf

서비스 재시작

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

참고사이트

2 Comments

  1. asdf

    안녕하세요 글 잘 읽었습니다
    opkg 설치 이후 /etc/ipsec.d 디렉토리가 없다고 뜹니다.
    ipsec 명령어도 찾을 수 없다고 뜨는데 해결 방법 아실까요?

    • qquack

      정확히는 알 수 없지만 패키지가 제대로 설치되지 않은것 같습니다.
      strongswan을 패키지를 설치하면 /etc/ipsec.d 기본으로 생성되는 디렉토리 입니다.

      패키지 설치확인은 opkg list-installed | grep strongswan 명령으로 확인 할 수 있으며,
      패키지 상태확인 여부는 opkg status pakagename 명령으로 확인해 보시기 바랍니다.

      또한 /usr/sbin/ipsec , /etc/init.d/ipsec 화일은 strongswan-ipsec 패키지에 딸린 화일로
      opkg files strongswan-ipsec 명령으로 딸린 화일 확인 할 수 있습니다.

      일단 정상이 아니라면 패키지를 삭제 후 설치를 다시한번 해보시기 바라며
      그래도 문제가 있다면 로그화일을 확인해보시기 바랍니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다