---
title: "우분투 22.04에서 OpenVPN을 설정하여 안전한 원격 접근 구현하기"
description: "Ubuntu 22.04에서 OpenVPN을 설정하여 안전한 원격 접근을 구현하는 방법을 다루며, 필요한 패키지 설치, PKI 및 CA 구성, 서버 및 클라이언트 설정, 방화벽 및 네트워크 구성, 트러블슈팅 가이드를 포함합니다. 보안 강화를 위해 DDoS 방어 및 권한 최소화 방법도 설명하며, 인증서 관리와 포트 포워딩의 중요성을 강조합니다."
date: "2022-12-20"
last_modified: "2026-05-15T08:36:00.000Z"
type: "Post"
tags:
  - "ubuntu"
  - "OpenVPN"
  - "vpn"
  - "install"
  - "troubleshooting"
  - "Docs"
categories:
  - "📗 Docs"
canonical_url: "https://blog.pieroot.xyz/ubuntu-2204-openvpn"
markdown_url: "https://blog.pieroot.xyz/ubuntu-2204-openvpn.md"
---

# 우분투 22.04에서 OpenVPN을 설정하여 안전한 원격 접근 구현하기

Ubuntu 22.04에서 OpenVPN을 설정하여 안전한 원격 접근을 구현하는 방법을 다루며, 필요한 패키지 설치, PKI 및 CA 구성, 서버 및 클라이언트 설정, 방화벽 및 네트워크 구성, 트러블슈팅 가이드를 포함합니다. 보안 강화를 위해 DDoS 방어 및 권한 최소화 방법도 설명하며, 인증서 관리와 포트 포워딩의 중요성을 강조합니다.

## 들어가며

안녕하세요! 오늘은 Ubuntu 서버에서 **OpenVPN**을 구축하는 방법을 공유하려고 합니다.

현재 서버에는 Samba를 이용한 파일 공유 시스템이 구축되어 있는데요, 이 시스템은 내부망(LAN)에서는 문제없이 동작하지만 **외부망(WAN)으로 넘어가는 순간** 접속이 불가능하고, 설령 접속되더라도 암호화가 되지 않아 보안상 문제가 있었습니다.

그래서 외부에서 안전하게 접속할 수 있는 방법으로 **VPN**을 선택하게 되었습니다. VPN을 사용하면 패킷을 암호화하여 전송하기 때문에 보안 위험을 크게 줄일 수 있거든요! 🔐

> **이 글에서 다루는 내용**
> 
> - OpenVPN 서버 구축 및 설정
> 
> - 클라이언트 인증서 생성 및 관리
> 
> - 방화벽 및 네트워크 설정
> 
> - 트러블슈팅 가이드
> 
> - 계정 생성/제거 자동화 스크립트

> **환경 정보**
> 
> - Ubuntu 22.04 LTS Server
> 
> - Easy-RSA와 OpenVPN이 동일한 서버에서 작동
> 
> - 참고: DigitalOcean OpenVPN 가이드

![image](https://blog.pieroot.xyz/api/image-proxy?id=88754e7d-988c-483e-b345-bb6a647320eb&kind=s3&pageId=21e067c0-15d0-80ba-9ae1-f5ec51da8b8d&source=block&blockId=2e4067c0-15d0-80a4-a491-e60a777359de)

---

### 🤔 왜 OpenVPN인가?

VPN 프로토콜에는 PPTP, L2TP, IPsec, WireGuard 등 다양한 선택지가 있습니다. 그중에서 OpenVPN을 선택한 이유는 다음과 같습니다:

#### OpenVPN vs WireGuard 비교

> **선택 기준**
> 
> - **OpenVPN**: 검증된 안정성, 다양한 환경 호환, 방화벽 우회 필요 시
> 
> - **WireGuard**: 최신 기술, 빠른 속도, 간단한 설정 선호 시
> 
> 저는 오픈소스이고 예전에 구축 경험이 있어서 OpenVPN을 선택했습니다. WireGuard 설정 방법은 추후에 별도로 포스팅할 예정입니다! 🚀

### 1️⃣ 필요한 패키지 설치

```shell
$ sudo apt update
$ sudo apt install openvpn easy-rsa
```

원격 저장소 정보를 갱신한 후 필수 패키지를 설치합니다.

```shell
$ mkdir ~/easy-rsa
```

설치한 Easy-RSA의 파일을 링크시킬 위치를 생성합니다.

```shell
$ ln -s /usr/share/easy-rsa/* ~/easy-rsa/
```

패키지 파일을 생성한 디렉토리에 심볼릭 링크로 연결합니다. 이렇게 하면 패키지 업데이트 시 자동으로 버전이 올라가기 때문에 이 방법을 채택했습니다.

```shell
$ sudo chown <본인 계정> ~/easy-rsa
$ sudo chmod 700 ~/easy-rsa
```

생성한 디렉토리를 관리자만 접근할 수 있도록 권한을 설정합니다.

### 2️⃣ PKI 및 CA 구성

```shell
$ cd ~/easy-rsa
```

생성한 디렉토리로 이동합니다.

```shell
$ cp vars.example vars
$ vi ~/easy-rsa/vars
```

vars 파일을 수정합니다.

![image](https://blog.pieroot.xyz/api/image-proxy?id=78dd863a-31f8-431f-a886-49cbc2e6c35f&kind=s3&pageId=21e067c0-15d0-80ba-9ae1-f5ec51da8b8d&source=block&blockId=21e067c0-15d0-80fe-83f3-c1d005a145ca)

```shell
set_var EASYRSA_DIGEST "sha512"
```
*~/easy-rsa/vars*

기본값인 SHA256을 사용해도 되지만, 보안성을 높이기 위해 원하는 값으로 변경해도 괜찮습니다.

```bash
#set_var EASYRSA_ALGO rsa

->

set_var EASYRSA_ALGO ec
```
*~/easy-rsa/vars*

기본값은 RSA이며, EC로 변경할 경우 후에 [Diffie-Hellman](https://ko.wikipedia.org/wiki/%EB%94%94%ED%94%BC-%ED%97%AC%EB%A8%BC_%ED%82%A4_%EA%B5%90%ED%99%98) 키를 사용하지 않습니다.

필요한 정보를 충분히 수정했다면 저장 후 종료합니다.

```shell
$ ./easyrsa init-pki
```

`init-pki` 명령으로 PKI 디렉토리를 생성합니다. PKI는 Public Key Infrastructure의 약자로, 생성할 키들이 저장될 위치를 초기화합니다.

```shell
$ ./easyrsa build-ca nopass
```

`build-ca` 명령으로 CA(인증 기관)를 구성합니다. `nopass` 옵션을 사용하면 **pass phrase** 입력을 생략할 수 있습니다.

> nopass 명령을 사용하지 않을 때에는 **pass phrase** 를 직접 입력해야하며
> 잊었을경우 새로 만들어야 하므로 반드시 기억해야합니다

pass phrase 입력 후 common name을 지정하지 않으면 기본값인 Easy-RSA로 CA가 등록됩니다.

```shell
$ ./easyrsa gen-req server nopass
```

인증서에 사용할 이름을 입력합니다. 여기서는 `server`로 지정했습니다.

> 다른 이름으로 바꾸어도 괜찮지만, 이름 변경 시 이후 파일에서도 추가 수정 작업이 필요합니다.

CA 지정할 때와 마찬가지로 `nopass` 옵션으로 **pass phrase** 입력을 생략합니다.

```shell
$ sudo cp ~/easy-rsa/pki/private/server.key /etc/openvpn/server/
```

생성된 server.key를 `/etc/openvpn/server`에 복사합니다.

```shell
$ ./easyrsa sign-req server server
```

`sign-req` 명령에서 server 뒤에는 방금 생성한 서버 이름을 입력합니다.

![image](https://blog.pieroot.xyz/api/image-proxy?id=35773168-8db1-445d-a72f-23427ca16d37&kind=s3&pageId=21e067c0-15d0-80ba-9ae1-f5ec51da8b8d&source=block&blockId=21e067c0-15d0-80b8-ba90-ecf4759e4b58)

825일간 인증서 사용이 가능한 것을 확인할 수 있습니다.

```shell
$ sudo cp ~/easy-rsa/pki/issued/server.crt /etc/openvpn/server/
$ sudo cp ~/easy-rsa/pki/ca.crt /etc/openvpn/server/
```

생성된 crt 파일들을 `/etc/openvpn`으로 복사합니다.

```shell
# $ ./easyrsa gen-dh
# 18 버전에서는 사용하며 우린 사용하지 않을 예정이다
```

Ubuntu 18 버전의 경우 [Diffie-Hellman](https://ko.wikipedia.org/wiki/%EB%94%94%ED%94%BC-%ED%97%AC%EB%A8%BC_%ED%82%A4_%EA%B5%90%ED%99%98) 키를 생성하는 것을 권고하지만, 20 버전 이후로는 EC 알고리즘이 대신 키 교환을 수행합니다. 구버전에서는 키 교환 시 필요했지만, EC 알고리즘을 사용하면 굳이 하지 않아도 괜찮습니다.

```shell
# $ openvpn --genkey --secret ta.key

openvpn --genkey tls-auth ta.key 
```

ta.key를 생성합니다. ta.key는 DDoS 공격과 UDP 포트 플러딩 공격 방지용으로 사용됩니다.

```shell
# $ sudo cp ~/easy-rsa/pki/dh.pem /etc/openvpn/server/ 
# 우린 생성하지 않았기에 복사할 dh.pem 파일이 없습니다

$ sudo cp ~/easy-rsa/ta.key /etc/openvpn/server/
```

생성한 키들을 `/etc/openvpn/`으로 복사합니다.

```shell
$ mkdir -p ~/client-configs/keys
```

생성한 계정들의 정보와 접속에 필요한 정보들을 저장할 디렉토리를 생성합니다.

```shell
$ ./easyrsa gen-req client1 nopass
```

접속할 클라이언트를 추가하는 작업입니다. 하나의 접속 계정당 하나씩만 연결이 가능하기 때문에 사용자당 하나씩 생성해야 합니다.

```shell
$ cp ~/easy-rsa/pki/private/client1.key ~/client-configs/keys/
```

생성한 key 파일을 따로 옮겨둡니다.

```shell
$ ./easyrsa sign-req client client1
```

생성한 key 파일로 인증서를 생성합니다.

![image](https://blog.pieroot.xyz/api/image-proxy?id=898b00b0-e67f-4c9a-8ea4-2ef93ffc2774&kind=s3&pageId=21e067c0-15d0-80ba-9ae1-f5ec51da8b8d&source=block&blockId=21e067c0-15d0-807f-9e11-f1bfc6ad11b9)

인증서 이름이 제대로 되었는지 확인한 후 `yes`를 입력합니다.

```shell
$ cp ~/easy-rsa/pki/issued/client1.crt ~/client-configs/keys/
```

생성한 인증서를 복사합니다.

```shell
$ cp ~/easy-rsa/ta.key ~/client-configs/keys/
$ cp /etc/openvpn/server/ca.crt ~/client-configs/keys/
```

기존에 생성한 서버의 인증서들을 복사합니다.

```shell
$ cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf /etc/openvpn/server/
```

OpenVPN 패키지 설치 시 생성된 server.conf 파일을 `/etc/openvpn/`으로 복사한 후 해당 파일을 수정합니다.

Docker의 경우 해당 파일이 존재하지 않아서 [GitHub](https://github.com/OpenVPN/openvpn/blob/master/sample/sample-config-files/server.conf)에서 가져옵니다.

```shell
$ vi /etc/openvpn/server/server.conf
```

```bash
# For extra security beyond that provided
# by SSL/TLS, create an "HMAC firewall"
# to help block DoS attacks and UDP port flooding.
#
# Generate with:
#   openvpn --genkey tls-auth ta.key
#
# The server and each client must have
# a copy of this key.
# The second parameter should be '0'
# on the server and '1' on the clients.
tls-auth ta.key 0 # This file is secret

->

tls-crypt ta.key
```
*vi /etc/openvpn/server/server.conf*

위에서 `openvpn --genkey --secret ta.key`로 생성했다면 `tls-crypt ta.key`로 변경합니다. `openvpn --genkey tls-auth ta.key`로 생성했다면 기본값으로 둡니다.

```bash
# Select a cryptographic cipher.
# This config item must be copied to
# the client config file as well.
# Note that v2.4 client/server will automatically
# negotiate AES-256-GCM in TLS mode.
# See also the ncp-cipher option in the manpage
cipher AES-256-CBC
```
*vi /etc/openvpn/server/server.conf*

위의 구문을 주석 처리하고 `cipher AES-256-GCM`을 추가합니다.

```bash
;cipher AES-256-CBC
cipher AES-256-GCM
```
*vi /etc/openvpn/server/server.conf*

`cipher AES-256-GCM`이 더 나은 수준의 암호화와 성능을 제공합니다. 그 아래에 `auth SHA256`을 추가합니다.

```bash
;cipher AES-256-CBC
cipher AES-256-GCM
auth SHA256
```
*vi /etc/openvpn/server/server.conf*

```bash
;dh dh2048.pem    # 주석 추가
dh dh.pem         # vars 파일의 #set_var EASYRSA_ALGO "rsa" 일때 사용 -> dh 파일을 생성했을 때
dh none           # vars 파일의 #set_var EASYRSA_ALGO "ec" 일때 사용
```
*vi /etc/openvpn/server/server.conf*

DH 키를 만들지 않았으므로 `dh dh2048.pem` 구문을 주석 처리하고 `dh none` 구문을 추가합니다.

```bash
# It's a good idea to reduce the OpenVPN
# daemon's privileges after initialization.
#
# You can uncomment this out on
# non-Windows systems.
;user nobody
;group nobody

->

user nobody
group nogroup
```
*vi /etc/openvpn/server/server.conf*

`user nobody` 및 `group nogroup` 줄을 찾아 주석을 제거합니다. 다만 `group nobody`로 되어 있으므로 `nogroup`으로 변경해야 합니다.

#### (선택 사항) 포트 번호와 연결 프로토콜을 선택할 경우

---

```bash
# Which TCP/UDP port should OpenVPN listen on?
# If you want to run multiple OpenVPN instances
# on the same machine, use a different port
# number for each one.  You will need to
# open up this port on your firewall.
port 1194

# TCP or UDP server?
;proto tcp
proto udp

-> 

proto tcp
;proto udp
```
*vi /etc/openvpn/server/server.conf*

우선 포트 번호와 프로토콜을 본인이 편한 것으로 설정합니다.

> 443번을 보통 많이 사용하는데, 443번이 HTTPS를 사용하는 포트로 방화벽에 걸리지 않고 쉽게 열려 있기 때문에 자주 사용됩니다.

> 하지만 저자는 HTTPS를 호스팅하는 데 443번 포트를 사용하고 있으므로, 포트는 기존(1194)을 유지하며 TCP로 변경합니다.

```bash
explicit-exit-notify 1

->

explicit-exit-notify 0
```
*vi /etc/openvpn/server/server.conf*

TCP로 변경할 경우 파일 끝에 해당 구문을 1에서 0으로 변경합니다.

#### (선택 사항) 서버의 이름을 직접 변경했을 경우

---

만약 `./easyrsa gen-req server` 명령에서 서버 이름을 다른 것으로 수정했을 경우,

```bash
cert server.crt
key server.key
```
*vi /etc/openvpn/server/server.conf*

이 부분의 `server`를 입력한 서버 이름으로 변경해야 합니다.

#### (선택 사항) VPN 서버가 존재하는 내부망과 통신이 필요한 경우

---

```bash
# Push routes to the client to allow it
# to reach other private subnets behind
# the server.  Remember that these
# private subnets will also need
# to know to route the OpenVPN client
# address pool (10.8.0.0/255.255.255.0)
# back to the OpenVPN server.
;push "route 192.168.10.0 255.255.255.0"
;push "route 192.168.20.0 255.255.255.0"

-> 

push "route 192.168.50.0 255.255.255.0"
```
*vi /etc/openvpn/server/server.conf*

서버가 존재하는 망(ex\> IP: 192.168.50.0 / subnet: 255.255.255.0)을 설정하고 주석(;)을 해제합니다. 서버가 연결되어 있는 인터페이스에 VPN을 통해 들어오는 패킷을 라우팅해주는 역할을 합니다.

### 3️⃣ 서버의 네트워크 구성

```shell
$ sudo vi /etc/sysctl.conf
```

해당 파일에서 네트워킹 포워딩을 허용해야 합니다.

```bash
# net.ipv4.ip_forward=1

->

net.ipv4.ip_forward=1
```
*vi /etc/sysctl.conf*

저 부분을 찾아 `#` 주석을 해제합니다.

```bash
$ sudo sysctl -p
```

명령어를 입력하여 설정이 정상적으로 적용되었는지 확인합니다.

```shell
Output
net.ipv4.ip_forward = 1
```

우선 외부와 통신하는 인터페이스를 확인해야 합니다.

```shell
$ ip route list default
```

```shell
Output
default via 192.168.50.1 dev enp4s0 proto dhcp src 192.168.50.3 metric 100
```

위에서 보라색으로 표시된 부분을 확인해야 합니다. 저자의 경우 `enp4s0`이 외부와 통신하는 인터페이스입니다.

```shell
$ sudo vi /etc/ufw/before.rules
```

방화벽 규칙을 수정하여 VPN으로 들어오는 패킷이 통신할 수 있도록 포워딩을 설정해야 합니다.

```bash
#
# rules.before
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
#   ufw-before-input
#   ufw-before-output
#   ufw-before-forward
#
 
# START OPENVPN RULES
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
# Allow traffic from OpenVPN client to enp4s0 (change to the interface you discovered!)
-A POSTROUTING -s 10.8.0.0/8 -o enp4s0 -j MASQUERADE
COMMIT
# END OPENVPN RULES
 
# Don't delete these required lines, otherwise there will be errors
*filter
. . .
```

위 구문(붉은 부분)을 추가한 후 저장합니다. 포워딩 규칙을 설정한 것입니다.

보라색 부분을 장비의 인터페이스 이름으로 변경합니다. 

```shell
$ sudo vi /etc/default/ufw
```

해당 파일을 열어서 `DEFAULT_FORWARD_POLICY` 지시문을 찾아 값을 `DROP`에서 `ACCEPT`로 변경합니다. 설정한 포워딩 규칙을 허용하는 것입니다. 저장 후 종료합니다.

저자의 경우 port: 1194 / protocol: tcp를 사용했으므로

```shell
$ sudo ufw allow 1194/tcp    # openvpn 허용
$	sudo ufw allow OpenSSH     # ssh 포트 허용 sftp 전송용
```

명령어로 방화벽을 허용합니다.

```shell
$ sudo systemctl -f enable openvpn-server@server.service
```

서버가 부팅될 때 자동으로 실행되도록 설정합니다.

```shell
$ sudo systemctl start openvpn-server@server.service
$ sudo systemctl status openvpn-server@server.service
```

openvpn-server를 실행하고 상태를 확인합니다.

```shell
$ mkdir -p ~/client-configs/files
$ sudo cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/client-configs/base.conf

$ vi ~/client-configs/base.conf
```

클라이언트를 생성하기 위한 파일을 수정합니다.

```bash
# The hostname/IP and port of the server.
# You can have multiple remote entries
# to load balance between the servers.
remote <서버의 공인 아이피> 1194
```

클라이언트에서 접속할 서버의 IP 또는 도메인과 포트 번호를 입력합니다.

```bash
# Are we connecting to a TCP or
# UDP server?  Use the same setting as
# on the server.
proto tcp
;proto udp
```
*vi ~/client-configs/base.conf*

`proto`를 찾아서 tcp로 변경하기 위해 주석(;)을 변경합니다.

```bash
# Downgrade privileges after initialization (non-Windows only)
user nobody
group nogroup
```
*vi ~/client-configs/base.conf*

해당 부분을 찾아서 주석을 해제하고 group의 그룹명을 `nogroup`으로 변경합니다.

```bash
# SSL/TLS parms.
# See the server config file for more
# description.  It's best to use
# a separate .crt/.key file pair
# for each client.  A single ca
# file can be used for all clients.
;ca ca.crt
;cert client.crt
;key client.key
```
*vi ~/client-configs/base.conf*

`ca`, `cert`, `key` 해당 부분을 모두 주석 처리합니다.

```bash
# Select a cryptographic cipher.
# If the cipher option is used on the server
# then you must also specify it here.
# Note that v2.4 client/server will automatically
# negotiate AES-256-GCM in TLS mode.
# See also the data-ciphers option in the manpage
;cipher AES-256-CBC
cipher AES-256-GCM
auth SHA256
```
*vi ~/client-configs/base.conf*

`cipher AES-256-CBC` 구문을 주석 처리하고 아래에 해당 구문을 추가합니다.

```bash
key-direction 1
```
*vi ~/client-configs/base.conf*

`auth` 아래에 추가합니다.

```bash
;script-security 2
;up /etc/openvpn/update-resolv-conf
;down /etc/openvpn/update-resolv-conf
;down-pre
;dhcp-option DOMAIN-ROUTE .
```
*vi ~/client-configs/base.conf*

리눅스 계열 클라이언트에서 사용하기 위한 구문으로, 파일의 가장 아래에 추가합니다.

모두 작성을 완료했다면 저장하고 종료합니다.

```shell
$ sudo vi ~/client-configs/make_config.sh
```

```bash
#!/bin/bash
 
# First argument: Client identifier
 
KEY_DIR=~/client-configs/keys
OUTPUT_DIR=~/client-configs/files
BASE_CONFIG=~/client-configs/base.conf
 
cat ${BASE_CONFIG} \
    <(echo -e '<ca>') \
    ${KEY_DIR}/ca.crt \
    <(echo -e '</ca>\n<cert>') \
    ${KEY_DIR}/${1}.crt \
    <(echo -e '</cert>\n<key>') \
    ${KEY_DIR}/${1}.key \
    <(echo -e '</key>\n<tls-crypt>') \
    ${KEY_DIR}/ta.key \
    <(echo -e '</tls-crypt>') \
    > ${OUTPUT_DIR}/${1}.ovpn
```
*vi ~/client-configs/make\_config.sh*

ca, key 파일이 정상적으로 존재할 경우 base.conf 파일을 ovpn 파일로 생성합니다.

```shell
$ chmod 700 ~/client-configs/make_config.sh
```

실행 권한을 설정합니다.

```shell
$ cd ~/client-configs
$ ./make_config.sh client1
```

위의 파일을 이용하여 클라이언트 파일을 생성합니다.

```shell
$ ls ~/client-configs/files

Output
client1.ovpn
```

생성이 정상적으로 되었는지 확인합니다. 해당 파일은 OpenVPN 클라이언트에서 접속하는 데 필요한 파일이므로 따로 저장해둡니다.

새로운 계정을 만들 때마다 매번 코드를 입력하기 귀찮고, 꼬이면 더 귀찮아지므로 쉘 스크립트 파일을 제작했습니다.

```bash
$ vi ~/easy-rsa/make_key.sh
```

```bash
#!/bin/bash
 
# First argument: Client identifier

PKI_DIR=~/easy-rsa/pki
PRIVATE=~/easy-rsa/pki/private
ISSUED=~/easy-rsa/pki/issued
CLIENT_KEY=~/client-configs/keys

./easyrsa gen-req ${1} nopass
cp $PRIVATE/${1}.key $CLIENT_KEY
./easyrsa sign-req client ${1}
cp $ISSUED/${1}.crt $CLIENT_KEY
```
*vi ~/easy-rsa/make\_key.sh*

파라미터로 받은 이름을 키로 만들어서 `~/client-configs/keys`에 바로 복사까지 해주는 스크립트입니다.

### 🔧 트러블슈팅

#### 그룹 미생성으로 실행 불가

```shell
failed to find gid for group nobody
```

본인은 이런 오류가 뜨면서 실행은 되었지만 연결이 되지 않는 문제가 발생했습니다. 아마 group에 `nobody`가 조회되지 않아 발생하는 문제로 추측됩니다.

설정 파일에서는 user: nobody / group: nobody로 되어 있으나, 직접 서버의 그룹을 확인해본 결과 group: nobody가 존재하지 않았습니다.

우리가 사용한 OS의 상태와 맞추어야 하기 때문에 `/etc/openvpn/server/server.conf`의 `group nobody` 부분을 아래처럼 수정하면 정상적으로 동작합니다.

```bash
# It's a good idea to reduce the OpenVPN
# daemon's privileges after initialization.
#
# You can uncomment this out on
# non-Windows systems.
user nobody
group nobody

->

suer nobody
group nogroup
```

또한 `~/client-configs/base.conf`의 group도 동일하게 수정해야 합니다. 수정 후 `systemctl restart openvpn-server@server.service`로 실행이 되지 않는다면, `openvpn /etc/openvpn/server/server.conf`를 실행하면 정상적으로 다시 실행됩니다.

#### 해외에서 국내 스트리밍 서비스 접속 불가

여행으로 베트남에 와보니 국내 스트리밍 서비스에 접근이 불가능했습니다.

VPN을 접속하면 소위 "아이피 세탁"이라고 하는 서버의 IP로 접근이 되어야 하지만, 베트남 현지의 IP로 접근되어 해외망 접속 금지로 걸렸습니다.

추가로 찾아보니 트래픽을 VPN으로 강제하려면 추가로 변경해야 합니다.

통신에 쓰이는 패킷들이 모두 서버를 통하도록 하여 해외에서 국내 콘텐츠를 접속할 수 있게 해주는 역할을 합니다.

```shell
push "redirect-gateway def1 bypass-dhcp"
```
*vi /etc/openvpn/server/server.conf*

VPN에 접속한 클라이언트는 DNS 서버를 아래 서버로 교체합니다.

```shell
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
```

### 🗑️ 계정 제거

생성한 VPN 클라이언트의 연결을 막기 위해 제거할 필요가 있습니다.

```shell
$ cd ~/easy-rsa/

$ ./easyrsa revoke client1
```

`revoke` 명령어가 클라이언트를 제거해주는 명령어이지만, 이렇게 입력해도 연결은 계속 됩니다.

제거한 인증서도 따로 기록해야 서버가 확인할 수 있습니다.

```shell
$ ./easyrsa gen-crl
```

위의 명령어를 입력하여 리스트(**certificate revocation list**)를 만들어야 합니다.

```shell
$ sudo ln -s ~/easy-rsa/pki/crl.pem /etc/openvpn/server/
```

만든 리스트를 openvpn-server 데몬 프로세스가 확인할 수 있도록 설정 파일이 있는 위치로 링크합니다.

복사해도 괜찮지만, 그렇게 하면 매번 복사해야 하므로 귀찮아집니다.

```shell
$ sudo vi /etc/openvpn/server/server.conf
```

server.conf 파일 가장 아래줄에 `crl-verify crl.pem`을 추가한 후 아래 명령어로 재시작합니다.

```shell
$ sudo systemctl restart openvpn-server@server.service
```

서버를 재시작해야 계정 제거가 완료됩니다.

---

### 📋 핵심 정리

이 글에서는 Ubuntu 22.04에서 OpenVPN 서버를 구축하는 전체 과정을 다루었습니다.

✅ **PKI 구성**: Easy-RSA를 사용한 CA 및 인증서 생성

✅ **서버 설정**: AES-256-GCM 암호화, TLS 인증 적용

✅ **네트워크 설정**: IP 포워딩, NAT 마스커레이드, UFW 방화벽 구성

✅ **클라이언트 관리**: .ovpn 파일 생성 및 계정 추가/제거 자동화

✅ **보안 강화**: ta.key로 DDoS 방어, 권한 최소화

---

### ⚠️ 주의사항

- **인증서 관리**: CA 키와 클라이언트 키는 안전하게 보관하세요

- **포트 포워딩**: 공유기 사용 시 OpenVPN 포트를 포워딩해야 합니다

- **정기 업데이트**: 보안 패치를 위해 OpenVPN을 최신 버전으로 유지하세요

- **백업**: `/etc/openvpn/`과 `~/easy-rsa/pki/` 디렉토리를 정기적으로 백업하세요

---

### 마치며

이 글을 처음 작성했을 때가 고등학생 시절이었습니다. 학교 인터넷에서 막히는 사이트들이 너무 많았고, 해외 여행 시에도 국내 OTT 서비스가 막혀서 우회하기 위해 처음 OpenVPN을 구축했었죠. 😅

OpenVPN은 서버-클라이언트 구조와 TCP 통신으로 인해 지연시간이 다소 발생하는 단점이 있습니다. 요즘은 **WireGuard**라는 Peer-to-Peer 방식의 VPN 시스템이 더 빠르고 설정도 간단해서 많이 사용되고 있습니다. WireGuard 구축 방법은 다음 포스팅에서 다루겠습니다! 🚀

---

### 📚 참고 자료

- DigitalOcean - How To Set Up an OpenVPN Server on Ubuntu 22.04

- [OpenVPN 공식 문서](https://openvpn.net/community-resources/)

- [Diffie-Hellman 키 교환 - Wikipedia](https://ko.wikipedia.org/wiki/%EB%94%94%ED%94%BC-%ED%97%AC%EB%A8%BC_%ED%82%A4_%EA%B5%90%ED%99%98)

- [NordVPN - WireGuard vs OpenVPN 비교](https://nordvpn.com/ko/blog/openvpn-vs-wireguard/)
