Journey to AWS
AWS와 같은 퍼블릭 클라우드 환경을 사용하다 보면 가끔 온프레미스 환경에서의 편안함(?)이 그리워질 때가 있습니다. 특히 온프레미스 환경에서는 사무실과 IDC 간에 네트워크가 연결되어 있기 때문에 사설망이라고 해도 큰 어려움 없이 접근할 수 있습니다. 하지만 퍼블릭 클라우드의 경우 사설망에 직접 접근하기 위해서는 AWS Client VPN이나 Site-to-Site VPN 등을 사용해서 연결 작업을 해줘야 하기 때문에 규모가 작은 스타트업 같은 곳에서는 구축에 어려움이 있습니다. 그래서 이번 글에서는 OpenVPN을 이용해서 AWS 사설망에 있는 서비스들을 마치 로컬에 있는 것처럼 편하게 사용할 수 있는 방법에 대해서 살펴보겠습니다. 하지만 이 연동 과정은 보안 상 위험에 노출될 수 있기 때문에 가급적 개발/스테이지 환경과 같은 곳에만 적용해보시길 권고합니다.
먼저 VPN에 대해서 살펴보겠습니다. VPN은 Virtual Private Network의 약자로 실제로는 인터넷망과 같은 공중망을 사용하지만 종단 간의 암호화를 통해서 마치 나만 사용하는 사설망과 같이 사용할 수 있게 해주는 기술입니다. 그리고 OpenVPN은 VPN 기술을 간편하게 구현할 수 있게 해주는 애플리케이션 중 하나입니다. (https://openvpn.net/)
AWS ClientVPN은 AD와 같이 사용자 인증 시스템을 구축해야 하는 번거로움이 있고 Site-to-Site VPN은 VPN 연동을 위한 하드웨어 장비를 필요로 한다는 어려움이 있어서 소규모의 스타트업에서 사용 하기에는 어려움이 있습니다. 그래서 상대적으로 쉽게 설치하고 유지보수할 수 있는 OpenVPN을 이용해서 사설망 접근을 구현해 보겠습니다.
OpenVPN을 설치하기 위해 EC2 인스턴스를 하나 만들어 보겠습니다. Amazon Linux 2를 사용해도 좋지만 설치 편의성을 위해서 Ubuntu 로 만들어 보겠습니다. 인스턴스 타입은 자유롭게 해도 되지만 OpenVPN 인스턴스는 외부에서 접근이 가능해야 하기 때문에 꼭 Public IP를 사용할 수 있도록 만들어 줍니다.
그리고 OpenVPN은 UDP 1194 포트를 사용하기 때문에 UDP 1194에 대한 접근 권한도 SecurityGroup에 꼭 포함될 수 있도록 설정해 줍니다.
OpenVPN 설치는 Docker 이미지를 통해 docker-compose로 설치합니다. Docker 이미지는 필요한 라이브러리 및 애플리케이션이 전부 포함하고 있기 때문에 Docker를 이용하면 훨씬 빠르게 설치할 수 있습니다.
먼저 아래와 같이 Docker를 설치해 줍니다.
자세한 설치 과정은 https://docs.docker.com/engine/install/ubuntu/ 참고
Docker 설치가 완료되었다면 Docker Compose를 설치해 줍니다.
자세한 설치 과정은 https://docs.docker.com/compose/install/ 참고
여기까지 준비되었다면 이제 본격적으로 OpenVPN을 설치해 보겠습니다.
먼저 OpenVPN 과 관련된 설정을 저장할 디렉터리를 하나 생성합니다. openvpn 이라고 명명하겠습니다.
그리고 docker-compose.yaml 파일을 생성해 줍니다.
version: "3.7"
services:
openvpn:
container_name: openvpn
image: wheelybird/openvpn-ldap-otp:v1.4
environment:
OVPN_SERVER_CN: "vpn.domain.com"
OVPN_ENABLE_COMPRESSION: "false"
OVPN_NETWORK: "172.16.0.0 255.255.255.0"
OVPN_ROUTES: "172.16.0.0 255.255.250.0, 10.10.0.0 255.255.0.0"
OVPN_NAT: "true"
OVPN_DNS_SERVERS: "10.10.0.2"
OVPN_REGISTER_DNS: "false"
USE_CLIENT_CERTIFICATE: "true"
cap_add:
- NET_ADMIN
volumes:
- openvpn-data:/etc/openvpn
ports:
- "1194:1194/udp"
networks:
- openvpn
logging:
driver: "json-file"
options:
max-size: "8m"
max-file: "10"
restart: unless-stopped
networks:
openvpn: {}
volumes:
openvpn-data: {}
OVPN_SERVER_CN은 OpenVPN이 사용할 도메인입니다. 자신에게 맞는 값을 설정해 줍니다. OVPN_NETWORK는 OpenVPN이 사용하게 될 IP 대역입니다. OpenVPN 클라이언트와 EC2 인스턴스에 설치된 서버가 통신하기 위한 IP 대역이기 때문에 AWS에서 사용하고 있는 대역과 겹치지 않는 아무 사설 대역을 설정해 주면 됩니다.
그리고 OVPN_ROUTE는 OpenVPN을 통해서 라우팅 할 IP 대역입니다. OpenVPN이 사용할 IP 대역과 AWS 상의 사설 대역을 포함시켜 주면 됩니다. OpenVPN 클라이언트가 OpenVPN 서버를 통해 OVPN_ROUTE에 있는 대역과 통신하게 됩니다.
그리고 docker-compose up -d 명령을 통해 Docker 를 실행시켜 줍니다.
OpenVPN 이미지를 잘 받아서 실행한 것을 볼 수 있습니다. 이제 클라이언트 설정을 위해 설정 파일을 생성해 보겠습니다. docker 명령을 통해 컨테이너에 직접 들어가서 클라이언트를 위한 설정을 생성합니다.
그림 스크린샷과 같이 설정 정보가 출력되는데요 이 출력 정보를 그대로 복사해서 XXX.ovpn 이라는 이름으로 저장해 줍니다.
마지막으로 https://openvpn.net/vpn-client/ 에서 OpenVPN 클라이언트를 다운로드해서 설치해 줍니다.
OpenVPN 클라이언트를 실행하고 나면 아래와 같은 초기화 화면이 나타납니다.
여기서 아까 복사해온 XXX.ovpn 파일을 추가해 줍니다.
Add 버튼을 클릭하게 되면 모든 설정이 완료됩니다.
이제 연결 버튼을 클릭해서 OpenVPN에 잘 붙는지 확인해 봅니다.
설정에 문제가 없다면 위와 같이 연결된 화면을 볼 수 있습니다.
이제 OpenVPN 설정이 완료되었으니 우리가 의도했던 대로 사설망에 자유롭게 붙을 수 있는지 살펴보겠습니다.
AWS의 여러 서비스 중 Elasticache는 공인 IP를 가지지 못해서 AWS 상의 사설망에만 존재할 수 있는 대표적인 서비스 중 하나입니다. 만약 OpenVPN이 없다면 개발망에 위치한 Elasticache에 연결하기 위해 좀 더 복잡한 포트 포워딩 같은 방법을 사용해야 할 수도 있습니다. 하지만 우리에겐 OpenVPN이 있으니 편하게 연결할 수 있습니다.
먼저 OpenVPN 연결 없이 telnet 으로 연결해 보겠습니다.
당연히 접속이 안 되는 것을 볼 수 있습니다. 주소 자체도 사설 대역이기도 하기 때문에 라우팅 자체도 원하는 대로 되지 않았을 겁니다. 하지만 OpenVPN 을 연결하게 되면 어떻게 될까요?
아까와는 다르게 잘 연결되어서 info 명령의 결과도 잘 가져오는 것을 확인할 수 있습니다.
우리가 이번 글에서 구축한 OpenVPN은 아래와 같이 동작하게 됩니다.
EC2 인스턴스에 설치된 OpenVPN 서버가 일종의 포트 포워딩을 해주는 역할을 한다고 이해하면 됩니다. 그래서 EC2 인스턴스가 설치된 VPC 외에 피어링을 맺고 있다면 피어링을 맺은 다른 VPC에 있는 DB와도 OpenVPN을 통해서 접근할 수 있게 됩니다. 물론 OVPN_ROUTE에 피어링을 맺은 VPC의 IP 대역을 추가해 줘야겠죠.
OpenVPN 은 AWS 사설망을 편하게 사용할 수 있도록 해주는 여러 도구 중 하나입니다. 대기업이나 일정 수준 이상의 규모를 갖추고 있는 곳보다는 빠른 개발과 업무 속도가 필요한 스타트업의 경우에 더 도움이 될 거라고 생각합니다. 로컬 개발 시에 개발 환경에 있는 DB나 Redis에 직접 연결해서 개발할 수 있다면 아무래도 개발 생산성에 도움이 되는 건 사실이니까요. 하지만 편한만큼 보안적인 위험은 있습니다. 이번 글에서는 빠르게 구축하기 위해 개별 사용자 인증 기능은 제외했지만 OpenVPN 에도 LDAP을 이용한 개별 사용자 인증이 가능하기 때문에 좀 더 안전하게 환경을 꾸리기 위해서는 인증 기능을 붙이는 것이 좋습니다. 감사합니다.