IT 관련/우분투(Ubuntu) 이것저것

Ubuntu 서버에 VPN 설치

islet2 2025. 4. 28. 22:05

Ubuntu 서버에 VPN 설치: Docker와 WireGuard로 쉽고 안전하게 구축하기

안녕하세요! 요즘 개인 정보 보호와 보안에 대한 관심이 높아지면서 VPN(Virtual Private Network) 사용이 늘어나고 있습니다. VPN을 사용하면 어떤 점이 좋을까요? 카페나 공항 같은 공용 Wi-Fi를 사용할 때 내 인터넷 통신 내용을 암호화해서 다른 사람이 엿보기 어렵게 만들어 보안을 강화할 수 있습니다. 또한, 집이나 사무실 밖에 있을 때도 마치 내부 네트워크에 있는 것처럼 안전하게 접속해서 파일 서버나 다른 기기를 이용할 수도 있죠.

이번 글에서는 Ubuntu나 Debian 계열 리눅스 서버 (라즈베리파이나 바나나파이 같은 작은 개인 서버도 가능해요!)에 직접 VPN 서버를 구축하는 방법을 알아보겠습니다. 특히 요즘 많이 사용하는 Docker와 빠르고 가벼운 WireGuard 기술을 이용해서, 비교적 간단하고 관리하기 쉽게 만들어 볼 거예요. Docker를 쓰면 설치 과정이 훨씬 단순해지고, 설정을 파일로 관리할 수 있어서 나중에 고치거나 다시 설치하기도 편하답니다.

시작하기 전에 확인해주세요! (사전 준비 사항)

본격적으로 설치를 시작하기 전에 몇 가지 준비물이 필요합니다.

  1. Ubuntu/Debian 기반 서버: 당연히 VPN 서버 역할을 할 리눅스 컴퓨터가 필요합니다. 인터넷에 연결되어 있어야 하고요. 이 글에서는 서버의 내부 IP 주소가 192.168.0.60 이라고 가정하고 설명할게요. 여러분의 서버 IP 주소에 맞게 바꿔서 따라오시면 됩니다.
  2. Docker 와 Docker Compose: 서버에 Docker와 Docker Compose 프로그램이 설치되어 있어야 합니다. 터미널에서 sudo docker versionsudo docker-compose version 명령어를 쳐서 설치되어 있는지, 버전 정보가 잘 나오는지 확인해보세요. 만약 설치되어 있지 않다면, Docker 공식 웹사이트의 설치 안내 문서를 참고해서 설치해주세요. (Get Docker, Install Docker Compose)
  3. 도메인 이름 (선택 사항이지만 추천!): 집에서 서버를 돌린다면 인터넷 IP 주소가 가끔 바뀔 수 있어요 (유동 IP). 이럴 때 IP 주소 대신 항상 같은 이름으로 접속할 수 있게 도메인을 사용하는 것이 편리합니다. 도메인이 있다면 IP가 바뀌어도 자동으로 새 IP를 알려주는 DDNS(Dynamic DNS) 기능을 사용할 수 있거든요. 이 글에서는 vpn.aaaa.org 라는 도메인을 예시로 사용할게요. Cloudflare 같은 곳에서 도메인을 관리하면 DDNS 설정도 쉽게 할 수 있습니다.
  4. 공유기 관리자 권한: 외부에서 VPN 서버로 접속하려면 공유기에서 특정 통신 길(포트)을 열어주는 설정(포트 포워딩)을 해야 합니다. 이걸 하려면 공유기 관리자 페이지에 접속할 수 있어야 해요.

자, 준비가 되셨다면 이제 본격적으로 설치를 시작해볼까요?

1단계: 설정 파일 저장할 폴더 만들기

WireGuard를 Docker로 실행하면 서버 설정이나 접속할 사용자(클라이언트) 설정 같은 중요한 파일들이 만들어집니다. Docker 컨테이너가 꺼지거나 다시 시작해도 이 설정들이 사라지지 않도록, 서버의 특정 폴더에 저장하고 Docker 컨테이너와 연결해 줄 거예요.

터미널을 열고 아래 명령어를 입력해서 폴더를 만들어 줍니다.

sudo mkdir -p /srv/docker/wireguard/config

이 명령어는 /srv 라는 폴더 아래에 docker 폴더를, 그 아래에 wireguard 폴더를, 또 그 아래에 config 폴더를 차례대로 만들어줍니다 (-p 옵션 덕분에 중간 폴더가 없어도 알아서 만들어줘요). /srv 폴더는 보통 서버 관련 데이터를 두는 곳으로 많이 사용됩니다.

이제 앞으로 작업하기 편하게 방금 만든 폴더로 이동할게요.

cd /srv/docker/wireguard

2단계: Docker Compose 설정 파일 만들기

Docker 컨테이너를 실행할 때는 여러 가지 옵션을 줘야 하는데, 이걸 매번 명령어로 길게 치는 건 번거롭죠. 그래서 docker-compose.yml 이라는 설정 파일을 만들어서 여기에 옵션들을 미리 적어두고 한 번에 실행할 거예요.

방금 이동한 /srv/docker/wireguard 폴더 안에 docker-compose.yml 이라는 이름으로 파일을 만들고 아래 내용을 넣어주세요. nano 라는 편집기를 사용해서 만들어 보겠습니다.

sudo nano docker-compose.yml

아래 내용을 복사해서 붙여넣으세요. 주의! YAML 파일은 각 줄 앞의 띄어쓰기(들여쓰기)가 아주 중요합니다. 아래 내용과 똑같이 들여쓰기를 맞춰주세요.

version: "3.8"
services:
  wireguard:
    image: linuxserver/wireguard
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      # 파일을 만들 때 사용할 사용자(PUID)와 그룹(PGID) ID입니다.
      # 터미널에서 'id -u' 와 'id -g' 를 쳐서 나오는 숫자로 바꿔주세요. (보통 1000)
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Seoul # 서버 시간 기준 설정 (한국 시간)
      # VPN 클라이언트가 접속할 주소입니다. 여러분의 도메인이나 공인 IP 주소를 넣으세요.
      - SERVERURL=vpn.aaaa.org
      # WireGuard가 사용할 통신 포트 번호 (UDP 방식)
      - SERVERPORT=51820
      # 몇 명의 사용자(클라이언트) 설정을 만들지 정합니다. (예: 스마트폰 1명, 노트북 1명 = 2)
      - PEERS=2
      # VPN 사용자가 인터넷 접속 시 사용할 DNS 서버 (auto는 서버 설정 따름, 1.1.1.1 이나 8.8.8.8 등 지정 가능)
      - PEERDNS=auto
      # VPN 내부에서 사용할 가상 IP 주소 범위
      - INTERNAL_SUBNET=10.13.13.0/24
    volumes:
      # 현재 폴더(.) 아래의 config 폴더를 Docker 컨테이너 안의 /config 폴더와 연결
      - ./config:/config
      # 서버의 커널 모듈을 컨테이너 안에서도 쓸 수 있게 연결
      - /lib/modules:/lib/modules
    ports:
      # 서버의 UDP 51820 포트를 컨테이너의 UDP 51820 포트와 연결
      - "51820:51820/udp"
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
    restart: unless-stopped # 서버가 켜지거나 예기치 않게 꺼졌을 때 자동으로 다시 시작

여기서 몇 가지 중요한 부분을 꼭 확인하고 여러분의 환경에 맞게 고쳐주셔야 해요.

  • SERVERURL=vpn.aaaa.org: 이 부분을 여러분이 사용할 도메인 이름이나 서버의 공인 IP 주소로 바꿔주세요. 도메인이 없다면 공인 IP 주소를 직접 써도 되지만, IP 주소는 바뀔 수 있다는 점을 기억하세요.
  • PEERS=2: VPN을 사용할 기기(스마트폰, 노트북 등)가 몇 대인지 생각해서 숫자를 정해주세요. 나중에 바꿀 수도 있습니다.
  • PUID=1000, PGID=1000: 이 부분은 서버에서 파일을 만들 때 누구의 권한으로 만들지를 정하는 거예요. 보통 서버에 처음 만든 사용자 계정의 ID가 1000인데, 혹시 다를 수도 있으니 터미널에서 id -uid -g 명령어를 쳐서 나오는 숫자로 바꿔주시면 더 좋습니다.

내용을 다 입력했으면 nano 편집기에서 Ctrl 키와 X 키를 같이 누르고, 저장할 거냐고 물으면 Y 키를 누르고, 파일 이름을 확인한 후 Enter 키를 눌러서 저장하고 빠져나옵니다.

3단계: WireGuard 컨테이너 실행하기

자, 이제 설정 파일도 만들었으니 이걸 이용해서 WireGuard 서버 역할을 할 Docker 컨테이너를 실행시켜 봅시다.

터미널에서 현재 위치가 아까 docker-compose.yml 파일을 저장한 /srv/docker/wireguard 폴더인지 확인 한번 해주시고요 (pwd 명령어). 맞다면 아래 명령어를 실행합니다.

sudo docker compose up -d

이 명령어를 실행하면 Docker가 필요한 이미지를 인터넷에서 다운로드하고, 설정 파일에 적힌 대로 컨테이너를 만들어서 백그라운드에서 실행시켜 줍니다 (-d 옵션).

잠시 기다렸다가 아래 명령어로 컨테이너가 잘 실행되고 있는지 확인해 보세요.

sudo docker compose ps

결과 목록에 wireguard 라는 이름의 서비스 상태(State)가 Up 이라고 나오면 성공적으로 실행된 겁니다! 혹시 문제가 있다면 sudo docker-compose logs wireguard 명령어로 로그를 확인해서 원인을 찾아볼 수 있습니다.

4단계: 클라이언트 설정 파일 가져오기

서버가 잘 실행되었으니, 이제 스마트폰이나 PC 같은 클라이언트 기기에서 VPN에 접속할 때 필요한 설정 정보를 가져와야 합니다. Docker 컨테이너가 실행되면서 /srv/docker/wireguard/config 폴더 안에 클라이언트별 설정 파일을 자동으로 만들어 두었을 거예요.

어떤 파일들이 만들어졌는지 한번 볼까요?

ls -al /srv/docker/wireguard/config/

아마 peer1, peer2 같은 폴더들이 보일 겁니다 (아까 PEERS=2 로 설정했기 때문이죠). 각 폴더 안에는 해당 클라이언트 기기에서 사용할 설정 파일(.conf)과 접속 정보를 담은 QR 코드 이미지 파일(.png)이 들어있어요.

# 예를 들어 peer1 폴더 안을 확인해 봅시다
ls -al /srv/docker/wireguard/config/peer1/

이제 이 파일들을 VPN을 사용할 기기(스마트폰, PC)로 가져와야 합니다.

  • 방법 1: QR 코드 사용 (스마트폰에서 편해요!)

    • WireGuard 스마트폰 앱에는 QR 코드를 찍어서 바로 설정을 추가하는 기능이 있습니다. 가장 쉬운 방법은 서버 터미널에 직접 QR 코드를 띄워서 스캔하는 거예요. qrencode 라는 도구가 필요한데, 설치되어 있지 않다면 sudo apt update && sudo apt install qrencode -y 명령어로 설치해주세요.
      # peer1 설정을 담은 QR 코드를 터미널에 보여줍니다 (터미널 창을 좀 키우고 실행하세요!)
      sudo qrencode -t ansiutf8 < /srv/docker/wireguard/config/peer1/peer1.conf
      터미널에 나타난 QR 코드를 스마트폰 WireGuard 앱으로 스캔하면 됩니다.
    • 아니면 peer1.png 파일을 PC로 복사한 다음, 스마트폰으로 옮겨서 앱에서 불러올 수도 있습니다.
  • 방법 2: 설정 파일(.conf) 사용 (PC 클라이언트 등)

    • PC용 WireGuard 클라이언트 프로그램은 설정 파일(.conf)을 직접 불러와서 추가할 수 있습니다. 서버에 있는 peer1.conf 파일을 PC로 복사해야 합니다. 파일을 복사하는 방법은 여러 가지가 있는데, SFTP 기능을 지원하는 프로그램(WinSCP, FileZilla, Cyberduck 등)을 사용하거나, 터미널에서 scp 명령어를 사용할 수 있습니다.
      # 예시: scp 명령어로 peer1.conf 파일을 PC의 '다운로드' 폴더로 복사하는 방법
      # (이 명령어는 PC의 터미널에서 실행해야 합니다!)
      # 'jongmin@192.168.0.60' 부분은 여러분의 서버 접속 정보로 바꿔주세요.
      scp jongmin@192.168.0.60:/srv/docker/wireguard/config/peer1/peer1.conf ~/Downloads/
      이렇게 복사한 .conf 파일을 PC의 WireGuard 프로그램에서 '파일에서 터널 가져오기' 같은 메뉴를 통해 추가하면 됩니다.

어떤 기기에서 어떤 Peer 설정을 사용할지 미리 정해두는 것이 좋습니다 (예: peer1은 내 스마트폰, peer2는 내 노트북).

5단계: 공유기 포트 포워딩 설정하기

이제 외부 인터넷에서 여러분의 VPN 서버로 접속 요청이 왔을 때, 공유기가 "아, 이 요청은 WireGuard 서버로 보내줘야 하는구나!" 하고 길을 열어주는 설정을 해야 합니다. 이걸 '포트 포워딩'이라고 불러요.

  1. 인터넷 브라우저를 열고 주소창에 공유기 관리 페이지 주소 (보통 192.168.0.1 이나 192.168.1.1)를 입력해서 접속합니다. (공유기 모델마다 주소나 ID/비밀번호는 다를 수 있어요.)
  2. 관리자 메뉴 중에서 '포트 포워딩', '가상 서버', '포트 포워드' 같은 항목을 찾으세요.
  3. 새로운 규칙을 추가하는데, 아래와 같은 내용을 입력합니다.
    • 외부 포트 (External Port): 51820
    • 내부 IP 주소 (Internal IP Address): 여러분의 WireGuard 서버 IP 주소 (예: 192.168.0.60)
    • 내부 포트 (Internal Port): 51820
    • 프로토콜 (Protocol): UDP (WireGuard는 UDP 방식을 사용해요!)
  4. 설정을 저장하고 공유기를 재부팅해야 적용되는 경우도 있습니다. (공유기 설명서를 참고하세요.)

6단계: 도메인 사용 시 DNS 설정하기 (Cloudflare 예시)

만약 docker-compose.yml 설정 파일의 SERVERURL에 도메인 이름(예: vpn.aaaa.org)을 사용하기로 했다면, 이 도메인 주소를 입력했을 때 여러분의 서버가 있는 곳의 실제 공인 IP 주소로 연결되도록 DNS 설정을 해주어야 합니다. 여기서는 Cloudflare 서비스를 사용하는 경우를 예로 들어 설명할게요.

  1. 먼저 여러분의 서버가 현재 사용 중인 공인 IP 주소를 알아야 합니다. 서버 터미널에서 curl ifconfig.mecurl icanhazip.com 같은 명령어를 실행하면 IP 주소가 나올 거예요.
  2. Cloudflare 웹사이트에 로그인해서 여러분의 도메인(aaaa.org) 관리 화면으로 들어갑니다. 'DNS' 설정 메뉴를 찾으세요.
  3. 새로운 DNS 레코드를 추가합니다.
    • 유형 (Type): A
    • 이름 (Name): vpn (이렇게 입력하면 전체 주소가 vpn.aaaa.org가 됩니다. 만약 도메인 자체(aaaa.org)를 쓰려면 @ 를 입력합니다.)
    • IPv4 주소 (Content): 위 1번에서 확인한 여러분의 공인 IP 주소를 여기에 입력합니다.
    • 프록시 상태 (Proxy status): 아주 중요! 구름 아이콘 모양의 프록시 상태를 반드시 'DNS 전용 (DNS only)' (회색 구름) 으로 설정해야 합니다. WireGuard는 Cloudflare의 주황색 구름 프록시 기능과 함께 사용할 수 없어요!
  4. 설정을 저장합니다. DNS 정보가 전 세계로 퍼지는 데 몇 분 정도 걸릴 수 있습니다.

7단계: 클라이언트 설정하고 연결 테스트하기

드디어 마지막 단계입니다! 이제 VPN을 사용할 스마트폰이나 PC에 WireGuard 클라이언트 프로그램을 설치하고, 4단계에서 가져온 설정 정보를 이용해서 연결을 시도해 볼 차례입니다.

  • WireGuard 클라이언트 프로그램 설치:
    • 스마트폰 (아이폰/안드로이드): 앱 스토어 또는 구글 플레이에서 'WireGuard'를 검색해서 공식 앱을 설치하세요.
      • iOS 앱 스토어: 링크
      • 안드로이드 구글 플레이: 링크
    • PC (윈도우/맥OS/리눅스): WireGuard 공식 웹사이트(https://www.wireguard.com/install/)에서 여러분의 운영체제에 맞는 버전을 다운로드해서 설치합니다.
  • 설정 추가하기:
    • 스마트폰: WireGuard 앱을 열고 오른쪽 아래 + 버튼을 누릅니다. 'QR 코드 스캔'을 선택해서 4단계에서 터미널에 띄웠던 QR 코드나 .png 이미지 파일을 스캔하거나, '파일에서 가져오기'를 눌러 .conf 파일을 선택하면 설정이 추가됩니다.
    • PC: WireGuard 프로그램을 실행하고 '터널 추가(Add Tunnel)' 버튼이나 '파일에서 터널 가져오기(Import tunnel(s) from file)' 버튼을 눌러서 4단계에서 PC로 복사해 둔 .conf 파일을 선택합니다.
  • 연결 테스트!
    1. 스마트폰 사용자라면 꼭! Wi-Fi를 끄고 모바일 데이터(LTE 또는 5G) 상태로 바꿔주세요. (집 Wi-Fi에 연결된 상태에서는 테스트가 제대로 안 될 수 있어요.)
    2. WireGuard 앱(또는 PC 프로그램)에서 방금 추가한 VPN 연결 설정 옆의 스위치를 켜서 연결을 시도합니다.
    3. 잠시 기다리면 연결 상태가 '활성(Active)'으로 바뀌고, '최근 핸드셰이크(Latest handshake)' 항목에 시간이 표시되고, 데이터 수신/송신 숫자가 조금씩 올라가는지 보세요. 이렇게 되면 성공적으로 연결되었을 가능성이 높습니다!
    4. 마지막 확인! VPN이 연결된 상태에서 스마트폰이나 PC의 인터넷 브라우저를 열고, 주소창에 https://ifconfig.mehttps://icanhazip.com 같은 IP 주소 확인 사이트에 접속해보세요. 이때 보이는 IP 주소가 여러분의 서버가 있는 곳(집이나 사무실)의 공인 IP 주소와 똑같이 나오면 완벽하게 성공한 겁니다! (원래 사용하던 모바일 데이터나 다른 네트워크의 IP가 아니라, VPN 서버를 통해 인터넷에 접속하게 된 거예요.)

8단계: 서버 방화벽 설정 확인하기 (ufw 사용 시)

혹시 Ubuntu 서버에서 ufw 라는 방화벽 프로그램을 사용하고 있다면, WireGuard가 사용하는 UDP 51820 포트를 방화벽에서 허용해주도록 규칙을 추가하는 것이 좋습니다. Docker가 자체적으로 네트워크 설정을 해서 ufw에서 막혀 있어도 작동하는 경우가 있긴 하지만, 나중에 헷갈리지 않고 안정적으로 사용하려면 명확하게 허용해주는 것이 좋습니다.

터미널에서 아래 명령어를 실행하세요.

# 현재 방화벽 상태 확인
sudo ufw status

# 만약 방화벽이 켜져 있다면(active), UDP 51820 포트 허용 규칙 추가
sudo ufw allow 51820/udp

# 변경된 방화벽 규칙 적용
sudo ufw reload

추가 정보: 유동 IP 와 DDNS 이야기

앞서 잠깐 언급했듯이, 집에서 사용하는 인터넷은 대부분 공인 IP 주소가 고정되어 있지 않고 가끔씩 바뀝니다 (유동 IP). 이렇게 IP 주소가 바뀌면 도메인(vpn.aaaa.org)이 엉뚱한 IP를 가리키게 되어서 VPN 접속이 안 될 수 있어요.

이 문제를 해결하는 방법이 바로 DDNS(Dynamic DNS) 입니다. DDNS는 내 서버의 IP 주소가 바뀔 때마다 자동으로 Cloudflare 같은 DNS 서비스에 알려줘서 도메인이 항상 올바른 IP 주소를 가리키도록 업데이트해주는 기술입니다.

이걸 설정하려면 보통 서버에 DDNS 클라이언트 프로그램이나 스크립트를 설치하고, 주기적으로 IP 주소를 체크해서 변경되었으면 Cloudflare에 자동으로 업데이트하도록 설정해야 합니다. "Cloudflare DDNS 스크립트" 같은 키워드로 인터넷에 검색해보시면 다양한 설정 방법들을 찾으실 수 있을 거예요. 이 부분은 조금 더 고급 설정에 해당하니, 일단 VPN 연결이 잘 되는 것을 확인한 후에 도전해보시는 것을 추천합니다.

마무리하며

축하합니다! 이제 여러분은 Docker와 WireGuard를 이용해서 자신만의 VPN 서버를 성공적으로 구축하셨습니다. 이제 공용 Wi-Fi를 사용할 때 좀 더 안심하고 인터넷을 사용하거나, 외부에서도 안전하게 내부 네트워크 자원에 접근하는 등 다양하게 활용해보세요.

혹시 VPN 연결이 잘 안 된다면, 당황하지 마시고 아래 내용들을 다시 한번 천천히 점검해보세요.

  • Docker 컨테이너가 잘 실행되고 있는지 로그 확인 (sudo docker-compose logs wireguard)
  • 공유기 포트 포워딩 설정 (UDP 51820 포트가 서버 IP로 정확히 연결되었는지)
  • 도메인을 사용한다면 Cloudflare DNS 설정 (A 레코드 IP 주소가 정확한지, 프록시는 꺼져 있는지)
  • 서버 방화벽 설정 (ufw 등에서 UDP 51820 포트가 열려 있는지)
  • 클라이언트 기기 설정 (서버 주소, 포트 번호 등이 정확한지)

이 가이드가 여러분의 안전하고 편리한 인터넷 생활에 조금이나마 도움이 되었기를 바랍니다!