- StrongSwan 기반 OpenStack과 AWS VPC 간 Site-to-Site IPsec VPN 구축
- 프라이빗 클라우드 환경과 퍼블릭 클라우드 연동해보기 위해 시작
과정
-
VPC 생성 - 퍼블릭 서브넷 생성 - 퍼블릭 서브넷 안에 EC2 생성
-
고객 게이트웨이 생성

- IP 주소 : StrongSwan을 설치할 VM이 사용하는 공인 IP
- VM의 공인 IP 대신 호스트 컴퓨터의 공인 IP를 사용.
- 상세 이유는 트러블 슈팅에 작성
-
가상 프라이빗 게이트웨이 생성

- AWS VPC의 VPN의 입구
- VGW 생성 후 VPC와 연결
-
VPN 연결 생성 (Site-to-Site VPN 연결)

- 위에서 만들었던 가상 프라이빗 게이트웨이와 고객 게이트웨이 ID 선택
- 라우팅 옵션 : 정적 선택 후, OpenStack의 사설 대역 10.0.0.0/24 입력
- 생성된 VPN을 선택하고, 구성 다운로드 버튼 클릭
-
서브넷과 연결된 VPC 라우팅 테이블에 대상: OpenStack 사설 대역(10.0.0.0/24), 대상: 가상 프라이빗 게이트웨이(vgw-xxxx) 추가
-
EC2 보안 그룹에 10.0.0.0/24에 대해 모든 트래픽 허용
-
OpenStack의 보안 그룹에서 AWS VPN 터널 1번과 2번으로부터 들어오는 포트를 허용
- ex) 15.165.181.204 / 43.200.194.148
- UDP 500 : ISAKMP (IKE 암호화 키 교환)
- UDP 4500 : IPsec NAT 데이터 전송
- ICMP ALL : Ping 테스트용
-
OpenStack 대시보드 > 프로젝트 > 네트워크 > 내부망 네트워크 선택 > 포트 > 인스턴스가 사용 중인 포트 편집 > 포트 보안 체크 해제

-
StrongSwan 설치 및 커널 설정
$ sudo apt update && sudo apt install strongswan strongswan-pki libcharon-extra-plugins
$ sudo sysctl -w net.ipv4.ip_forward=1
$ echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
$ sudo vi /etc/ipsec.secrets
[OpenStack VM 공인IP] 3.37.142.145 : PSK "5kkNNJ_qGpzjyfbV2_DOBuS1ByGYSV85"
[OpenStack VM 공인IP] 3.39.220.175 : PSK "5REcjuMvae96sqongVm5NdvD2aYUT6e6"
$ sudo vi /etc/ipsec.conf
config setup
charondebug="all"
uniqueids=yes
conn aws-tunnel-1
authby=secret
auto=start
left=%defaultroute
leftid=PublicIP
leftsubnet=10.0.0.0/24
right=3.37.142.145
rightid=3.37.142.145
rightsubnet=20.0.0.0/16
keyexchange=ikev1
ike=aes128-sha1-modp1024!
ikelifetime=28800s
esp=aes128-sha1-modp1024!
lifetime=3600s
type=tunnel
dpddelay=10s
dpdtimeout=30s
dpdaction=restart
conn aws-tunnel-2
authby=secret
auto=start
left=%defaultroute
leftid=PublicIP
leftsubnet=10.0.0.0/24
right=3.39.220.175
rightid=3.39.220.175
rightsubnet=172.31.0.0/16
keyexchange=ikev1
ike=aes128-sha1-modp1024!
ikelifetime=28800s
esp=aes128-sha1-modp1024!
lifetime=3600s
type=tunnel
dpddelay=10s
dpdtimeout=30s
dpdaction=restart
$ sudo ipsec restart
$ sudo ipsec status
학습
- AWS VPN 터널을 이용한 하이브리드 클라우드 구축
- 사설 IP 간 직접 통신
- 공인 IP(Floating IP) 없이도 두 클라우드의 인스턴스가 서로 통신할 수 있게 된다.
- VPN 연결 전 : OpenStack VM이 AWS EC2에 접속하려면 반드시 인터넷 망을 타고 EC2의 공인 IP로 접근해야 한다. (보안 취약)
- VPN 연결 후 : OpenStack VM에서 AWS 사설 IP로 연결이 가능하다. 반대로 마찬가지.
- 의미 : DB처럼 보안상 공인 IP를 할당하면 안 되는 자원들에 안전하게 접근할 수 있다.
- 데이터 보안 강화
- OpenStack과 AWS 사이를 오가는 모든 패킷은 aes128-sha 알고리즘으로 알호화된다.
- 기업용 프라이빗 클라우드 운영에서 보안 컴플라이언스를 충족하는 가장 기본적인 방법.
- 서비스 아키텍처 확장
- 프론트엔드는 확정성이 좋은 AWS EC2에 배치해 갑작스러운 트래픽에 대응하고,
- 백엔드/DB는 보안이 중요한 OpenStack에 배치한다.
- 터널을 통해 양쪽의 자원을 자유롭게 조합하는 멀티 티어 아키텍처를 구현할 수 있다.
- 터널 1번과 2번을 모두 사용해서 하나가 죽으면 즉시 다른 쪽으로 우회하는 BGP 라우팅이나 고가용성(HA) 설계를 사용한다.
고객 게이트웨이 (Customer Gateway, CGW)
- 정의 : AWS 외부(사용자의 온프레미스 데이터 센터 또는 오픈스택 환경)에 위치한 물리적 장치나 소프트웨어 애플리케이션에 대한 AWS 측의 논리적 리소스
- 역할 : AWS가 터널을 생성할 상대방의 정보를 정의한다. 여기에는 상대방 게이트웨이 장치의 공인 IP 주소와 BGP ASN(자율 시스템 번호) 등이 포함된다.
- 사용 이유 : VPN 연결을 맺기 위해서는 패킷을 보낼 목적지(Endpoint) 주소가 필요하다. AWS는 CGW를 통해 어디로 패킷을 암호화해서 보낼지를 인지하게 된다.
가상 프라이빗 게이트웨이 (Virtual Private Gateway, VGW)
- 정의 : AWS 측 VPC에 연결되는 VPN 종단점이다.
- 역할 : VPC와 외부 네트워크 간의 VPN 트래픽을 수신하고 분산하는 입구 역할을 한다.
- 사용 이유 : VPC 내부의 리소스들이 외부 네트워크와 통신할 때 일반적인 인터넷 게이트웨이(IGW)가 안인 보안된 터널을 통해 통신하도록 강제하기 위해 사용한다.
- VPC 하나에 하나의 VGW를 연결하여 보안 통신을 관리한다.
- VPN 연결 생성 시 두 게이트웨이가 사용된 이유
- VPN(Virtual Private Network)은 두 지점 사이의 가상 터널이다.
- 터널의 양 끝단 정의 : VPN 연결을 생성할 때
VGW는 AWS 측의 끝점, CGW는 오픈스택 측의 끝점을 의미한다.
- 협상 : 두 리소스를 연결함으로써 AWS는 누구와(CGW)와 어디를 통해(VGW) 보안 연결을 시도할지 결정하고, IPsec 프로토콜에 필요한 암호화 알고리즘 및 키 교환 협상을 시작할 수 있는 환경을 구축한다.
- VPN 연결 생성에서 정적 라우팅 및 오픈스택 대역(10.0.0.0/24) 입력 이유
- 정적 라우팅 이유 : 동적 라우팅(BGP)을 지원하지 않는 환경이거나, 네트워크 구조가 고정되어 있어 수동으로 경로를 지정하는 것이 관리상 명확할 때 선택한다.
- 대역 입력 이유 : AWS VPC 내부에 있는 리소스들은 기본적으로 10.0.0.0/24 라는 대역이 어디에 있는지 모른다.
- 전달 경로 지정 : 라우팅 옵션에 이 대역을 입력하면, AWS는 목적지 IP가 10.0.0.0/24인 패킷은 일반 인터넷으로 보내지 말고, 생성된 VPN 터널로 전달하라는 규칙을 생성하게 된다.
- StrongSwan과 설정 파일의 역할
StrongSwan : 리눅스 기반의 오픈소스 IPsec 구현체.
- 역할 : 표준 IPsec 프로토콜을 사용하여 VPN 터널을 생성, 관리, 암호화하는 서비스(데몬) 역할을 수행한다.
- 설정 파일
/etc/ipsec.conf : 터널의 논리적 구조와 암호화 정책을 정의
- left/right: 로컬과 원격지의 IP 정보 정의
- ike/esp: 암호화 알고리즘, 해시 알고리즘, DH 그룹 등 보안 파라미터 정의
- leftsubnet/rightsubnet: 터널을 통해 통신할 사설 네트워크 대역 정의
/etc/ipsec.secrets : 인증을 위한 공유 비밀키(Pre-Shared Key, PSK)를 저장
- 보안을 위해 설정 파일과 분리되어 관리되며, 상대방과 나의 공인 IP를 매칭하여 인증에 사용한다.
- UDP 500 및 UDP 4500 포트 개방 이유
- IPsec 통신을 위해서는 두 단계의 포트가 필요하다.
UDP 500 (ISAKMP)
- IKE(Internet Key Exchange) 프로토콜이 사용하는 포트.
- 터널을 맺기 전, 양측이 암호화 키를 안전하게 교환하고 상대를 인증하는 '협상 단계'에서 사용된다.
UDP 4500 (NAT-T)
- IPsec은 원래 네트워크 주소 변환(NAT) 환경에서 작동하기 어렵다.
- 게이트웨이가 사설 IP를 사용하거나 NAT 장비 뒤에 있을 경우, IPsec 패킷을 UDP로 캡슐화(NAT Traversal)하여 전송해야 한다. 이때 사용하는 포트가 4500이다.
- IPsec (Internet Protocol Security)이란?
- 정의 : IP 계층에서 보안을 제공하기 위한 프로토콜 스위트이다.
- 기능
- 기밀성 : 패킷을 암호화하여 제3자가 내용을 볼 수 없게 한다.
- 무결성 : 전송 중 데이터가 위조되거나 변조되지 않았음을 보장한다.
- 인증 : 통신하는 양 끝단이 신뢰할 수 있는 대상인지 확인한다.
- 작동 방식 : 크게 IKE(키 교환 및 정책 협상)와 ESP/AH(실제 데이터 암호화 및 전송) 프로토콜이 결합하여 하나의 안전한 가상 터널을 형성한다.
트러블 슈팅
- VPN 연결 생성 과정에서
Public IP VPNs must use a customer gateway with a public IP address. 에러 발생
- OpenStack 내부에서 외부망으로 사용하는 IP 대역을 192.168.35.0 대역으로 사용하고 있었기 때문에 고객 게이트웨이 등록 과정에서 192.168.35.228을 입력했다.
- 원인
- 고객 게이트웨이 등록하려는 IP 주소가 공인 IP 대역이 아닌 사설 IP 대역일 때 발생한다.
- AWS VPN 서비스는 인터넷 망을 통해 터널을 뚫어야 하므로, 상대방(OpenStack VM)의 주소가 인터넷에서 접근 가능한 공인 IP여야만 한다.
- OpenStack 환경이 이중 NAT 구조(집 공유기 안의 서버)이기 때문에 VM 내부에 할당된 IP와 외부에서 보이는 IP가 다르다.
- 해결
- VM 내부에서
curl ifconfig.me 명령어로 AWS가 인식할 수 있는 공인 IP를 확인
- 해당 IP는 내 데스크탑의 공인 IP와 같다.
- OpenStack에서 외부 인터넷으로 나갈 때 내부 망 IP -> 외부 망 IP -> 공유기의 공인 IP순으로 NAT를 거친다.
- 그렇기 때문에 OpenStack의 VM에서 나온 패킷을 외부에서 봤을 때는 공유기의 공인 IP로 보이게 된다.