회사에 AWS VPC를 구축 중인데, 로컬 환경에서 데이터 레이어에 대한 접근이 필요해졌다. 여러가지 대안책이 생각났는데 다음과 같은 방법들이 생각났다.
1. ACL에서 사내 IP만 다 열어준다.
2. bastion server를 만들어서 ssh 터널링을 뚫어준다.
3. AWS Client VPN 환경울 구축한다.
4. Selfhosted 로 VPN Server를 구축한다.
1번은 2~4번 다 시도해보고 안 되면 최후의 보루 처럼 적용하기로했다. 2번은 나쁘지 않은 생각 같았는데, 2번은 SSH를 통해서만 접근을 해야 하는게 단점으로 다가왔다. (비개발직군도 접근해야되는 리소스가 있기때문), 이제 남은건 VPN 방식인 3번 4번 이었는데 3번은 비용이 문제였다.
비용은 다음과 같다.
1. 10명이 하루 1시간씩 한달간 사용한다면, (총 사용시간 * 0.1) + (호스트 수 * 호스트 당 하루 시간 * 한 달 * 0.05) + 네트워크 비용
2. (10*1*30 * 0.1) + (10*1*30 * 0.05) + 네트워크 비용
3. 30 + 15 + 네트워크 비용
= 45$ + @
이 계산이면, 10명이 하루 3시간씩만 이용해도 150달러가 넘게 된다. 게다가 개개인이 PC를 안 끄고 간다거나, 하는 문제가 생겼을 때 대처 방법이 딱히 떠오르지 않았다. 그래서 결국 AWS Client VPN 도 포기하고 VPN Server를 직접 구축하고자했다.
이러면 사용자 추가별 비용은 생기지 않고, ec2 비용만 내면 된다! 마이크로 기준으로 월 10$ + @ 의 비용 산정이 나왔다.
처음에 찾아본건 Open VPN이다. 적당히 괜찮겠다 싶어서 구축하려고 딥하게 조사하다가 다음과 같은 글을 발견했다. https://www.top10vpn.com/guides/wireguard-vs-openvpn/
위 비교글을 보고 구축 하는 글들을 비교해보니, 너무 모든 상황이 딱 맞아 보였다. 더 빠르고, 더 간단하고 마치 apache를 보다가 nginx를 처음 접할때 느낌이랄까? 아니면 nginx를 보다가 haproxy를 봤을 때 느낌이랄까? 당장 EC2를 만들고 테스트 해봤다.
우리는 테라폼을 쓰고 있어서 빠르게 다음과 같이 EC2를 구축했다. init.sh는 docker 와 docker compose 설치가 들어있다.
resource "aws_security_group" "allow_tls" {
name = "allow_tls"
description = "Allow TLS inbound traffic"
vpc_id = var.vpc_id
ingress {
description = "TLS from VPC"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "TLS from VPC"
from_port = 51820
to_port = 51820
protocol = "udp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "TLS from VPC"
from_port = 51821
to_port = 51821
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
tags = {
Name = "allow_tls"
}
}
resource "aws_instance" "docker-test2" {
ami = "ami-0fd0765afb77bcca7"
instance_type = "t3.micro"
key_name = "tf-key-pair"
vpc_security_group_ids = [aws_security_group.allow_tls.id]
availability_zone = "ap-northeast-2a"
subnet_id = var.subnet_id_a
user_data = file("./init.sh")
root_block_device {
volume_size = 30
}
tags = {
Name = "wireguard"
}
}
#!/bin/bash
sudo amazon-linux-extras install docker
sudo service docker start
sudo usermod -a -G docker ec2-user
sudo curl -L https://github.com/docker/compose/releases/download/1.21.0/docker-compose-`uname -s`-`uname -m` | sudo tee /usr/local/bin/docker-compose > /dev/null
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
인터넷에 후다닥 Wireguard docker-compose를 검색해서 다음과 같이 컴포즈 파일을 작성했다.
version: '3'
services:
wg-easy:
environment:
# 필수 파라미터, 내 퍼블릭 아이피를 정해준다.
- WG_HOST=${PUBLIC_IP}
# 옵셔널 파라미터
- PASSWORD=foobar123
- WG_PORT=![](https://velog.velcdn.com/images/kikiki0611/post/432ebbbd-f320-4294-bd9d-572e98cf205d/image.png)
- WG_DEFAULT_ADDRESS=172.32.8.x # host ip와 다른 ip로 잡아야한다!
- WG_DEFAULT_DNS=1.1.1.1
- WG_ALLOWED_IPS=0.0.0.0/0
image: weejewel/wg-easy
container_name: wg-easy
network_mode: bridge
volumes:
- .:/etc/wireguard
ports:
- "51820:51820/udp"
- "51821:51821/tcp"
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
그리고 되게 별거 없이 docker-compose up
을 날려준다.
컴포즈가 다 올라가고 http://{ip}:52821 로 접속하면 패스워드를 입력하라고 나온다. 위에 설정했던 foobar123를 입력해주면
Client를 만들라고 나오는데, 여기에서 각 클라이언트별 인증키를 관리할 수 있다.
빠르게 new client로 테스트를 만들고나서 json 파일을 다운로드 받아보자.
필자는 Mac 환경이라 앱스토어에서 wireguard를 다운받았다.
다운받고 아까 client 인증 파일을 import 하면 설정 끝이다.
그럼 다음과 같이 VPN 연결 전 후로 내 아이피가 달라진걸 확인할 수 있다!
이렇게 꽤나 간단하게 VPN Server를 구축해봤다. 위에 문제라고 여겼던, SSH 터널링으로만 접근하지 않고 VPC에서 사용하는 네트워크 자체를 잡을 수 있게 됐고, 연결 호스트당 비용을 줄일 수 있었으며, 중앙에서 접속자들을 쉽게 관리할 수 있게 됐고 또 비개발 직군도 나름 쉽게(?) 접속할 수 있게 됐다.
이제 더 해볼건 internet 망을 막고 (VPN을 켠 상태로 인터넷을 하면 네트워크 비용 폭탄이 발생할거같다) 필요한 망에 대한 접근만 열어줄 생각이다.
이 방법도 찾게 되면 다음 포스팅에 이어서 작성할수 있도록 하겠다.
여기는 github! https://github.com/JoHwanhee/wireguard-playground