안녕하세요, 저는 인프라셀에서 데브옵스 엔지니어로 일하고 있는 박재현이라고 합니다. 데브시스터즈에서는 사내 인프라 혹은 클라우드 인프라 자원에 접근하기 위해서 OpenVPN을 사용해왔습니다. 이번 글에서는 OpenVPN에서 WireGuard 기반 VPN으로 전환하게 된 이유와 어떻게 VPN 시스템을 직접 구축하게 되었는지에 대해서 설명합니다. 글의 내용이 길고 주제에 대한 연관성으로 2부로 구성하게 되었습니다. 1부에서는 WireGuard에 대한 설명과, 커널 네트워킹 스택, 그리고 AWS의 네트워킹 스택에 대한 이야기를 합니다. 2부에서는 VPN 서버에서 사용하는 인증과 eBPF를 이용한 패킷 필터링, 그리고 eBPF를 이용한 유저 편의기능을 소개합니다.
#VPN?
VPN이란 Virtual Private Network의 약자로, 가상 사설망이라는 의미입니다. 일반적으로 사설망은 외부에서 접근이 안 되고, 사설망 내부에서만 통신을 할 수 있습니다. 예를 들어, 게임 서버와 데이터베이스는 외부에서 직접 접근하지 못하면서도 서로 통신은 할 수 있어야하기 때문에, 사설망 내부에 함께 두는 것이 적절합니다. 그런데 서버 개발 혹은 운영을 하다보면, 직접 그러한 자원들에 사람이 직접 접근해야할 필요가 종종 생깁니다. 이럴 때 VPN을 사용하게 되면, 외부 네트워크로부터 VPN 서버를 통해 사설망 내부 자원에 접근할 수 있게 됩니다.
VPN은 외부 네트워크와 사설 네트워크 망을 잇는 통로이기 때문에, 그만큼 보안이 중요합니다. 허가된 사용자만 접근할 수 있어야하며, 통신이 적절히 잘 암호화되어서 중간에서 도청 또한 불가능해야만 합니다. 이러한 요구조건 위에서 다른 편의기능을 추가한 여러 VPN 구현체들이 존재하고, 그 중에서 데브시스터즈는 OpenVPN이라는 솔루션을 사용하고 있었습니 다.
#왜 OpenVPN → WireGuard?
OpenVPN으로도 오랫동안 잘 사용하고 있었지만, 사용해오다보니 여러 가지 문제점들이 있었습니다.
- Single Sign-On(SSO) 연동이 불편합니다. 데브시스터즈는 Keycloak이라는 제품을 사용해 인증 및 권한 제어를 하고, Google 계정을 OAuth 2로 연동하여 사용하고 있습니다. 많은 서비스들을 여기서 제공하는 SSO로 인증을 수행하고 있었는데, OpenVPN에 연결할 때에 사용할 사용자 계정으로 SSO 연동을 하기 어려워 OpenVPN 계정은 따로 관리를 해야만 했고, 신규 입사자가 들어올 때마다 일일이 계정을 발급해주거나 퇴사자 처리를 할 때 따로 계정을 지워줘야 하는 등의 관리 상 불편함이 있었습니다.
- 사설망 접근 유저가 누구인지 접근 로그를 보고 특정을 하기가 어렵습니다. OpenVPN을 사용하고 있을 때, VPN 서버에서 사설망으로 가는 패킷에 대해 NAT(Network Address Translation)를 적용하고 있었습니다. 이렇게 하게 되면 NAT의 특성 상 사설망 자원들의 IP 로그에는 어떤 유저가 사용했는지에 관계 없이 모두 VPN 서버 자체의 IP가 찍히게 됩니다. 보안 사고 혹은 침해 사고 등에 대비하기 위해서는 VPN을 사용하더라도 어디에 누가 접근을 시도했는지 특정할 수 있으면 좋겠다는 의견이 있었습니다.
- OpenVPN 기업용 라이센스 관리가 불편합니다. 유저 수 만큼 비용이 늘어나는 데다가, 라이센스 만료에도 항상 신경쓰고 있어야하기 때문입니다.
- WireGuard와 비교해서 무겁고 느립니다. 여러 벤치마크 자료들을 봐도 레이턴시와 대역폭 측면에서 WireGuard가 우세에 있고, 초기 연결 속도 또한 체감이 될 정도로 차이가 납니다.
이러한 문제점들을 인식하고 있던 중, WireGuard를 사용한 VPN을 써보면 어떻겠냐는 의견이 나왔습니다.
#WireGuard?
WireGuard는 다른 VPN 솔루션들과는 달리 두 지점(Peer) 사이의 통신을 암호화하는 프로토콜에 대한 구현체입니다. WireGuard의 장점은 여러 가지가 있지만, 그 중 대표적인 것만 꼽아보면 다음과 같습니다.
- 속도와 레이턴시가 우수합니다. UDP만을 사용하며, 불안정한 연결 환경에서도 잘 작동하도록 설계되었습니다. 또한 Linux에 내장되어 있는 암호화 기법들을 사용하면서 잘 최적화되어 있어 암호화 성능도 좋고, 모바일이나 임베디드 환경에서도 사용하기 좋습니다.
- 첨단 암호화 기법을 사용하여 안전하며, 성능도 우수합니다. WireGuard에서 내부적으로 사용하는 Noise protocol framework는 Zero round trip, forward secrecy 등을 지원하여 매우 빠른 연결 속도와 더 나은 통신의 보안을 지원합니다. 또한, WireGuard에서 패킷 암호화에 사용하는 Curve25519, ChaCha20 Poly1305 등의 암호화 기법들은 다른 암호화 기법들과 비교하여 훨씬 안전하고 빠른 암호화를 지원합니다.
- Peer 배포가 쉽습니다. WireGuard에서 Peer끼리 정보를 주고 받을 때 공개키 암호화를 사용합니다. 이는 바꿔말하면, 공개키로 자신의 신원을 증명할 수 있다는 말입니다. 따라서 WireGuard 통신을 세팅할 때에는 공개키만 서로 알고 있다면 가능하기 때문에, 우 리가 자주 쓰는 SSH Key의 deploy 만큼이나 Peer 배포가 간단합니다.
- 연결이 안정적입니다. 일상 생활에서 스마트폰을 사용하다보면 와이파이와 LTE 네트워크 사이를 전환하는 등의 상황을 많이 접하곤 합니다. 이럴 때에 일반적인 TCP 연결이라면 재연결을 해야하는 상황이 벌어지기도 하여 사용 경험이 안 좋은 때가 있습니다. 하지만 WireGuard는 UDP만을 사용하고, 공개키를 기반으로 연결이 정의되면서 내부적으로 상태를 가지지 않는(Stateless) 특성 덕분에, 이러한 상황에서도 끊기지 않고 안정적이게 통신을 이어나갈 수 있고, 데몬 등으로 연결을 관리해주어야할 필요가 없어지기 때문에 연결 관리 코스트에서도 자유롭습니다.
- 리눅스에 내장되어있어 사용하기 편합니다. WireGuard는 리눅스 커널 5.6 버전부터 기본으로 포함되어 있어 그 버전 이상의 커널을 사용하면 따로 설치가 필요 없는데다가, 유저 공간의 어플리케이션이 아닌 커널 모듈로서 작동하기 때문에, 서버 어플리케이션이 비정상 종료 되어도 운영체제가 돌아가고 있는 한 WireGuard의 기능들은 모두 정상적으로 동작하여 안정적이기까지 합니다.
하지만 두 지점 사이의 통신을 구현한 프로토콜에 지나지 않기 때문에 다양한 부가 기능들로 무장한 다른 VPN 솔루션들과 편의성 측면에서는 매우 비교되는 것이 현실입니다. 바꿔말하면, 필요한 부분들을 직접 입맛에 맞게 구현해서 쓰면 유연성과 편의성, 그리고 위에 나열한 장점들까지 모두 가져갈 수 있는 좋은 VPN 솔루션을 구현할 수 있다는 결론에 다다를 수 있습니다.
