pfSense, OpenVPN Site-to-Site 구축하기
개요
AWS(Amazon Web Service) 인프라를 사용하는 경우 작업자(=개발자)와 인프라 연결의 효용성을 위해 VPN을 사용하게 된다. AWS의 Peer to Peer 혹은 AWS VPN/IPsec을 연결하면 손쉽게 VPN 연결을 확보할 수 있지만, A to B to C 간의 연결은 아직 지원하고 있지 않기 때문에, 확장성 대비 VPN 환경 구축은 거의 필수적이다.
여담이지만, 왜 VPN 을 사용할까?
- VPN 은 Server와 Client 간 모든 Packet 을 Symmetric Key를 이용해 암/복호화 하기 때문에 안전하다.
- PPT2/IPsec 등의 대안이 있지만, 무료 이면서 유지보수가 유용한 OpenVPN 을 차용한다.
참고 : http://kr.giganews.com/vyprvpn/compare-vpn-protocols.html (VPN 프로토콜 비교)
그럼 왜 OpenVPN 을 쓸까?
- PP2P 에 비해 빠르며, L2TP/IPsec과 대응한 속도를 갖는다.
- 연결 대기시간이 길고, 구간이 길어져도 Latency 가 짧다.
- 무선라우터와 불안정한 네트워크에서도 빠르고 안정적이다.
- Windows, Linux, macOS 등의, 대부분의 모든 플랫폼을 지원한다.
관리 편이성을 위해 GUI 환경을 지원하는 pfSense를 사용할 때 Site to Site 를 구축하는 방법을 정리했다. SITE-A to SITE-B 연동에 있어 SITE-A(Hub OpenVPN Server)만 pfSense를 사용한 경우로, SITE-B 는 OpenVPN Server를 그대로 사용했다.
pfSense 사용 이유
Linux 기반의 설치형 네트워크 툴로, GUI 환경으로 각종 네트워크 환경을 관리/제어할 수 있는데, 특징은 다음과 같다.
- URL : https://www.pfsense.org/
- FreeBSD 기반 / PHP(WebAPP)
- OpenVPN 및 IPsec 각종 방화벽 설정 지원
- OpenVPN Server/Client 동시 운영 가능
- ‘기간제’형 계정 및 인증서 제어 가능
pfSense를 선택한 이유는 GUI 환경에서 사용자 및 VPN 환경을 제어할 수 있기 때문이다. 보통 인프라 전담 인원을 두는 경우가 드물고, 이 역할 대부분을 개발자가 병행하는데, 모든 개발자가 같은 수준을 갖고 있는게 아니기 때문에, shell 명령어를 다루는게 쉽지 않을 수도 있다. 운영중인 VPN Service 에 명령이 잘못 전달되어 전체 서비스가 마비될 수도 있는 만큼, 관리의 편이성을 위해선 GUI 기반이 매우 유용하다. pfSense는?
- 편리한 인증서 관리가 가능하다. easy-rsa 를 사용하지 않아도 CA 및 복수개의 인증서 관리가 어렵지 않다.
- 인증서 별 기간 제한이 가능하다.
- 사용자 별 기간 제한 및 기능 제약을 둘 수 있다.
만약, 자사 이외에 협력사의 ID 까지 관리한다고 했을 때 별도의 관리 툴을 개발하지 않아도 pfSense 만으로도 충분 히 관리가 가능하기 때문에 일손을 덜 수 있다. 안타깝게도 AWS Instance에는 pfSense를 설치할 수 없다. 이미지 설치형이기 때문인데, AWS 의 Market Place 에서 구입 및 설치가 가능하다.
- URL : https://aws.amazon.com/marketplace/pp/B00G6P8CVW
- pfSense 를 구입한다. t2.micro 정도의 Instnace 도 충분히 쓸만하다.
- 가격이 그리 비싸지 않다. t2.micro 기준 한달 $60 선
pfSense의 설치는 어렵지 않다. AMI 구입 후 SSL 포트만 개방해 줌으로써 설치가 완료 되고, 나머지 모든 기능은 Web Interface 로 사용 할 수 있기 때문.
pfSense를 통해 SITE-B(10.10.0.0/16)의 Instance들을 접속해 사용해 보자.
VPN 기본 원리
VPN을 사용하면 물리적으로 분리되어 있는 두 개의 네트워크에 터널(Tunnel)을 생성 함으로써 하나의 네트워크로 만들게 된다.
- Workstation의 VPN Driver 와 AWS OpenVPN 은 동일한 Private IP 대역을 갖는다.
- Internet Traffic 은 각 환경의 Gateway 를 통해 전달되고, 사전 정의된 Subnet 만 Tunnel 을 통해 전달된다.
VPN 작업 이점
VPN 이 없는 경우
- Public Subnet에 위치한 Server는 작업자의 IP 를 알아야 한다. 원격지에서 작업할 경우 접근이 불가능하다.
- Server 의 Public IP 는 Static IP 가 아니다. (특별한 요청 없이 Elastic IP 는 3개로 제한된다)Private Subnet에 위치한 Server에 파일을 직접 올리기 쉽지 않다. 결국 SSH 터널링이 필요하거나, 파일 서버가 필요하다.
VPN 이 있는 경우
- 사용자의 트래픽을 모니터링할 수 있다.
- 사용자마다 작업 가능한 영역(Subnet)을 제어할 수 있다.
- 서버의 Private IP(Static IP)만 알고 있으면 다른 Region의 Subnet으로도 데이터 전송이 가능하다.
- 모든 통신은 SSL 에 의해 암호화 된다.
SITE-A to SITE-B
AWS 에 작업 환경 구축시 Operation Phase 및 Region 에 따른 Subnet 을 구분한다. 이 때 생성된 Subnet 을 연결하기 위해서는 Site-to-Site 형식으로 연결해야 한다. 개발자가 접속하는 pfSense가 있는 Site를 SITE-A, 개발용 EC2 Instance(=Server)가 위치하고 있는 Site를 SITE-B 라 명명하겠다.
전제조건
- 개발자(=운영자)의 Workstation은 VPN Client 가 설치되어 있다.
- VPC-MGMT OpenVPN Client 는 VPC-DV OpenVPN Server와 이미 연결 되어 있다.
패킷흐름
- 개발자가 10.10.201.50 EC2 Instance(S=Server) 에 접근하려고 한다.
- Developer VPN Client 는 VPC-MGMT-OpenVPN-Server 에서 부여된 Private IP 가 할당되어 있다.
- VPC-MGMT-OpenVPN-Server 는 Target(Destination)이 동일 Subnet 에 없음을 판단한다.
- VPC-MGMT-OpenVPN-Server 는 Internal Routing을 통해 VPC-MGMT-OpenVPN-Client로 패킷을 전달한다.
- VPC-DV-OpenVPN-Server는 Internal Routing을 통해 10.10.201.0/24의 Gateway(10.10.201.1) 에 패킷을 전달한다.
- 10.10.201.1 Gateway는 10.10.201.50으로 패킷을 전달한다.
1. SITE-A, pfSense 환경 구축
개발자가 접속할 pfSense. 즉 OpenVPN Server는 SITE-A(10.40.101.0/24) 에 존재한다. 이 OpenVPN Server는 사용자와 각각의 Subnet 을 연결할 Hub 역할 및 사용자 관리의 복합적 기능을 수행 할 것이다.
- 사용자/인증서 관리 : pfSense
- 트래픽 관리 : OpenVPN
OpenVPN Server 를 운영하려면 VPN Server를 위한 인증서를 생성해야 한다. shell 에서 인증서를 생성하려면 easy-rsa를 사용해야 하나, pfSense는 Web Interface에서 Key를 생성할 수 있다. 먼저 Certificate Authority를 생성하자. 이 CA 는 OpenVPN Server를 운영할 1개의 Server Key와 n개의 User Key로 구성될 것이다. 우선 Server Key 을 만들자.
CA 를 생성할 때 크게 주의해야 할 부분은 없다. 이제 Server Key를 생성하자.
Certificate Type 을 “Server Certificate”로 지정해야 하는 것 말고 특별히 주의해야 할 부분은 없다.
“Server Cert” 인증서가 생성됐다. 이 인증서는 OpenVPN Server를 구동할 때만 사용된다.
2. OpenVPN Server 생성
pfSense는 기본적으로 OpenVPN Server를 탑재하고 있다. 옵션만 지정해 주면 pfSense는 OpenVPN Server를 구동하려 할 것이다. OpenVPN Server 자체가 생성하는게 복잡하지 않은 만큼. pfSense 의 Server 생성도 그리 복잡하지 않다. VPN > OpenVPN > Servers > ADD+ 를 통해 신규 서버 생성이 가능하다.
- 서버 이름, 포트를 달리 하면 복수개의 서버도 쉽게 생성할 수 있다.
‘Local port’만 유심히 보자. 개발자는 UDP/1194 로 접속 되며, AWS 의 Security Group의 Inbound rules 에 이 정보를 추가해야 한다.
앞서 생성한 정보를 선택하면서 내려오자.
- TLS : TLS 를 사용하는 경우
- Peer CA : 1번 단계에서 생성한 CA
- Server Cert. : 1번 단계에서 생성한 서버용 인증서
- IPv4 Tunnel Network : VPN을 위한 Private IP 대역. 즉, 개발자에게 부여되는 사설 IP.
- Disable IPv6 : IPv6 을 사용하지 않는다면 체크한다.
Custom options 를 유심히 보자.
route 10.10.101.0 255.255.255.0 192.168.101.50
> 서버 라우팅 경로 지정
> 10.10.101.0/24 의 트래픽은 192.168.101.50 게이트웨이로 라우팅 (아래에서 언급할 예정)
> 192.168.101.50 은 반대편 Site 의 OpenVPN Server 에서 pfSense에 할당해 준 Static IP 다.push “route 10.10.101.0 255.255.255.0”
> 10.10.101.0/24 의 트래픽은 VPN Tunnel 을 사용할 것을 ‘사용자 Client’ 에 전송한다.
> openvpn client 로 접속할 때 client 의 log 에서 이 내용을 확인할 수 있다.
pfSense의 OpenVPN Server 설정이 완료되었다.
3. SITE-B(10.10.0.0/16) OpenVPN Server 설치
pfSense 가 Client 입장에서 접속하게 될 SITE-B 의 OpenVPN Server를 설치하자. SITE-B도 pfSense를 설치하면 매우 간단하지만, Server to Server 이기 때문에 사용자 관리가 필요 없으니 불필요한 비용 지출을 막을 수 있다. 만약, GUI 로 관리하고 싶다면 OpenVPN Access Server를 사용하자. 2 Users 까지는 무료이므로 사용에 지장이 없기 때문.
하지만, OpenVPN Server 를 설치하는 건 매우 간단한 일이다. OpenVPN 과 인증서를 생성해 줄 easy-rsa 를 설치하자. 아래의 작업은 uBuntu 16.04 기반으로 진행되었고, 다른 버전도 동일하다. OpenVPN 은 Server/Client 구분이 따로 없다. 경우에 따라 Diffie-Hellman Key 생성을 위해 openssl 이 필요한 경우도 있지만 AWS EC2 에는 openssl 이 기본 설치되어 있으므로 신경 쓸 필요 없다.
[shell]
sudo apt-get install openvpn easy-rsa
[/shell]
OpenVPN에서 사용할 CA와 인증서를 생성하자.
[shell]
cd /usr/share/easy-rsa
vi vars
…
export KEY_SIZE=2048
export KEY_COUNTRY ~ export KEY_EMAIL # 영역까지 수정
…
[/shell]
vars 는 인증서를 생성하기 위한 기본 사용자/서버 정보를 담고 있다. vars를 수정하면 번거롭게 동일한 정보를 매번 입력할 필요가 없게 된다.
KEY_SIZE는 복잡도를 증가시켜 안정성을 강화할 수 있다. 하지만, SERVER to SERVER 연결 인 만큼 신뢰구간을 확보했다 가정하고 이 키 크기를 줄여도 무관하다. 나머지 정보는 본인 정보게 맞게 입력하자.
[shell]
source ./vars
./clean-all
./build-ca
…
…
[/shell]
keys 디렉터리에 ca.crt와 ca.key 가 생성 되었을 것이고, Server Key 와 pfSense에서 사용할 client 를 생성하자. 여기서 pfSense 는 User 입장이다.
[shell]
./build-key-server server
./build-key NRT-DV-CC
[/shell]
keys 디렉터리에 server.crt, server.csr, server.key의 Server Key와 더불어 NRT-DV-CC.crt, NRT-DV-CC.csr, NRT-DV-CC.key 가 생성 되었다. 이들 파일을 uBuntu 의 기본 OpenVPN 환경 설정 폴더인 “/etc/openvpn” 로 복사하자.
[shell]
cp -r ./keys /etc/openvpn
chmod -R 600 ./keys #OpenVPN 은 Permission 이 600 인 Key/Cert 만 사용을 허가한다.
openssh dhparam -out /etc/openvpn/keys/dh2048.pem 2048 #대칭키 교환을 위한 Diffie-Hellman Key
[/shell]
이제 pfSense만을 위한 클라이언트 환경 설정을 지정하자. cso(Client Specific Overrides)폴더는 개별 클라이언트를 위한 정보를 포함하고 있다. 여기서 NRT-DV 는 인증서 생성 시 지정한 Common Name 과 동일해야 한다.
[shell]
mkdir /etc/openvpn/cso
vi /etc/openvpn/cso/NRT-DV
…
route 10.10.101.0 255.255.255.0 # 10.10.101.0/24를 OpenVPN Server를 통해 라우팅한다.
route 10.10.201.0 255.255.255.0
route 192.168.101.0 255.255.254.0
ifconfig 192.168.101.50 255.255.255.0 # pfSense에게 고정 IP 를 부여한다.
…
[/shell]
pfSense에게 고정IP를 부여하는 이유는 10.10.101.0/24, 10.10.201.0/24로 흘러야 하는 패킷에게 이 IP 로의 전달을 선언하기 위해서다. 이제 메인 환경 설정 파일을 만들자. uBuntu 에서의 위치는 /etc/openvpn/openvpn.conf 가 기본 경로다.
[shell]
vi /etc/openvpn/openvpn.conf
…
port 1194
proto udp
dev tun
keepalive 10 120
persist-key
persist-tun
ca keys/ca.crt
cert keys/server.crt
key keys/server.key
dh keys/dh2048.pem
server 192.168.101.0 255.255.255.0
cipher BF-CBC
comp-lzo no
client-to-client
verb 3
log /var/log/openvpn.log
status openvpn.log
client-config-dir cso
…
[/shell]
service openvpn restart를 통해 OpenVPN 을 가동하고, 변경된 라우팅 테이블을 확인해 보자.
[shell]
$route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.10.101.1 0.0.0.0 UG 0 0 0 eth0
10.10.101.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
192.168.101.50 0.0.0.0 255.255.255.0 U 0 0 0 as0t0
[/shell]
10.10.101.1은 이 Subnet의 기본 Gateway다. 192.168.101.50 가 모든 트래픽을 수용하고 있다.
한가지 더. 위에서 첨부 되어 있는 것과 같이 10.10.0.0/16 Subnet은 Public(10.10.101.0/24), Private(10.10.201.0/24) 의 Subnet을 갖고 있다. pfSense 가 10.10.201.0/24 패킷도 이 OpenVPN Server로 보낼거고, 이를 포워딩 하기 위해서 ip-forward 선언이 필요하다.
[shell]
vi /etc/sysctl.conf
…
net.ipv4.ip-forward = 1
…
[/shell]
즉시 반영은 “echo 1 > /proc/sys/net/ipv4/ip_forward”를 타이핑 하면 된다. 단, sysctl.conf에 추가하지 않으면 매 부팅시마다 값은 0으로 리셋된다. 그리고 AWS Console 에서 Source/Destination Check 을 Disable 로 변경해주자.
4. SITE-B OpenVPN Server에 연결할 SITE-A pfSense OpenVPN Client 생성
pfSense에 SITE-B 를 위한 Client를 생성한다. Client 를 생성하기 위해선 키/인증서 등록이 필요한데, 3번에서 생성한 정보를 통해 인증서를 Import 하도록 하자. 이 인증서는 VPN Client 추가 시 사용된다.
VPN > OpenVPN > Clients 의 +ADD 버튼을 눌러 Client 를 생성하자. 이 정보는 SITE-B OpenVPN Server 에 설정된 내용 그대로 옮겨올 뿐이다.
- Server host or address : SITE-B OpenVPN Server
- Encryption Algorithm : BF-CBC (기본)
- Auth digest algorithm : SHA1 (기본)
- Remote Network : SITE-B 의 Subnet
- Disable IPv6 : Check
저장과 동시에 pfSense는 SITE-B OpenVPN Server에 접속을 시도할 것이며, 그 결과가 Client Instance Statics에 보이게 된다. Virtual Address 에 위에서 선언한 192.168.101.50 으로 지정 되어 있음을 확인할 수 있다. 이 IP 는 SITE-B 로 접속할 Gateway 가 된다.
5. Internal Routing
pfSense의 OpenVPN Server 로 접속한 User가 pfSense가 Other Site 로 접속한 OpenVPN Client 로 접속하고자 한다면 Internal Routing 을 선언해야 한다. uBuntu 에서는 iptables 로 tun+ devices 간 설정을 해 주면 되지만, pfSense 에서는 Firewall > NAT > Outbound 에서 설정을 추가 해야 한다.
6. OpenVPN 사용자 생성
OpenVPN 을 사용할 ‘개발자’ 를 pfSense에 추가하자.
User-Manager를 통해 사용자를 생성할 수 있다. 이 사용자는 VPN Client 에서 인증용 ID/Password 로도 사용된다. 이제 이 사용자를 위한 인증서를 생성하자.
- System > Cert. Manager
- Certificates > +ADD 선택
- Certificate authority : 1번 단계에서 생성한 CA
- Certificate Type : User (사용자를 위한 인증서)
- Lifetime (days) : 인증서 유효기간. 이 기간이 끝나면 인증서를 갱신해야 한다.
- Common Name : 사용자를 위한 구분 이름. 필요시 이 설정이 CSO 에서 사용된다.
[생성] 완료.
다시 User Manager로 방문해 바로 앞에서 생성한 인증서를 추가하자.
7. 개발자용 OpenVPN Client 설정
6번에서 생성 및 설정한 인증서 기반으로 개발자에게 메일을 보내주면 된다. 필요한 내용은 다음과 같다.
- CA : System > Certificate Manager > CAs > “Export Key”
- CERT : System > Certificate Manager > Certificates > “Export Certificate”
- KEY : System > Certificate Manager > Certificates > “Export Key”
- TLS : VPN > OpenVPN > Servers > Edit > “TLS Key”
이들을 적당한 이름으로 저장하자. 그리고 아래와 같이 config.ovpn 을 수정하자.
[shell]
client
dev tun
remote pfsense.s-tune.com
ca ca.crt
cert gloriashield.crt
key gloriashield.key
tls-auth tls.key 1
cipher AES-256-CBC
comp-lzo no
proto udp
port 1194
log-append /var/log/openvpn.log
verb 3
# Use a persistent key and tunnel interface.
persist-tun
persist-key
[/shell]
그리고 OpenVPN 에 접속하게 되면 ID/Password 를 묻게 되는데, User Manage 에서 생성한 계정 정보를 입력함으로써 접속이 완료된다.
pfSense를 사용하면 OpenVPN 을 shell 에서 설치 및 환경 설정을 하는 것에 비해 매우 간단히 구축할 수 있다. 인원이 적은 회사에 월 몇 만원 단위로 사용할 수 있는 만큼 비용 대비 이득은 매우 크지 않을까?