Ubuntu Linux에 OpenVPN 설치 및 설정 가이드

OpenVPN 개요

OpenVPN은 오픈소스 VPN 솔루션으로, 안전한 원격 접속과 네트워크 간 통신을 제공합니다. SSL/TLS를 사용하여 강력한 암호화를 지원하며, 방화벽을 통과하기 쉬운 구조로 설계되어 있습니다.

1. OpenVPN 서버 설치

# 패키지 목록 업데이트
sudo apt update
sudo apt upgrade -y

# OpenVPN 설치
sudo apt install openvpn -y

# Easy-RSA 설치 (인증서 관리 도구)
sudo apt install easy-rsa -y

# OpenVPN 버전 확인
openvpn --version

# 설치된 파일 확인
dpkg -L openvpn | grep bin

2. PKI (Public Key Infrastructure) 설정

Easy-RSA 디렉토리 설정

# Easy-RSA 디렉토리 생성
make-cadir ~/openvpn-ca

# 디렉토리 이동
cd ~/openvpn-ca

CA (Certificate Authority) 설정

# vars 파일 편집
nano vars

# 다음 내용 수정 (예시)
set_var EASYRSA_REQ_COUNTRY "KR"
set_var EASYRSA_REQ_PROVINCE "Seoul"
set_var EASYRSA_REQ_CITY "Seoul"
set_var EASYRSA_REQ_ORG "MyCompany"
set_var EASYRSA_REQ_EMAIL "admin@example.com"
set_var EASYRSA_REQ_OU "IT Department"

PKI 초기화 및 CA 생성

# PKI 초기화
./easyrsa init-pki

# CA 생성 (비밀번호 설정 필요)
./easyrsa build-ca

# CA 인증서 확인
ls pki/ca.crt

3. 서버 인증서 및 키 생성

서버 인증서 생성

# 서버 인증서 요청 생성 (nopass: 비밀번호 없이)
./easyrsa gen-req server nopass

# 서버 인증서 서명
./easyrsa sign-req server server

# DH (Diffie-Hellman) 파라미터 생성 (시간이 오래 걸릴 수 있음)
./easyrsa gen-dh

# TLS 인증키 생성
openvpn --genkey secret ta.key
Using Easy-RSA 'vars' configuration:
* /home/ubuntu/openvpn-ca/vars

Using SSL:
* openssl OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024)
You are about to sign the following certificate:
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.
Request subject, to be signed as a server certificate
for '825' days:

subject=
commonName = server

Type the word 'yes' to continue, or any other input to abort.
Confirm request details: yes

Using configuration from /home/ubuntu/openvpn-ca/pki/openssl-easyrsa.cnf
Enter pass phrase for /home/ubuntu/openvpn-ca/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'server'
Certificate is to be certified until Apr 1 17:15:48 2028 GMT (825 days)

Write out database with 1 new entries
Database updated

Notice
------
Certificate created at:
* /home/ubuntu/openvpn-ca/pki/issued/server.crt

생성된 파일 확인

ls pki/issued/server.crt        # 서버 인증서
ls pki/private/server.key # 서버 개인키
ls pki/dh.pem # DH 파라미터
ls ta.key # TLS 인증키

4. 서버 설정 파일 구성

인증서 및 키 파일 복사

# OpenVPN 디렉토리로 파일 복사
sudo cp pki/ca.crt /etc/openvpn/server/
sudo cp pki/issued/server.crt /etc/openvpn/server/
sudo cp pki/private/server.key /etc/openvpn/server/
sudo cp pki/dh.pem /etc/openvpn/server/
sudo cp ta.key /etc/openvpn/server/

서버 설정 파일 생성

# 샘플 설정 파일 복사 (존재하는 경우)
sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf /etc/openvpn/server/

# 또는 직접 생성
sudo nano /etc/openvpn/server/server.conf

서버 설정 파일 내용 (server.conf)

# 포트 설정
port 1194

# 프로토콜 (udp 또는 tcp)
proto udp

# 가상 네트워크 인터페이스
dev tun

# 인증서 및 키 파일 경로
ca ca.crt
cert server.crt
key server.key
dh dh.pem

# VPN 서브넷 설정
server 10.8.0.0 255.255.255.0

# 클라이언트 설정 유지
ifconfig-pool-persist /var/log/openvpn/ipp.txt

# 클라이언트에게 기본 게이트웨이 푸시 (모든 트래픽을 VPN으로)
push "redirect-gateway def1 bypass-dhcp"

# DNS 서버 푸시
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

# 클라이언트 간 통신 허용 (선택사항)
client-to-client

# 연결 유지
keepalive 10 120

# TLS 인증
tls-auth ta.key 0

# 암호화 알고리즘
cipher AES-256-GCM
auth SHA256

# 압축 (보안상 비활성화 권장)
;comp-lzo

# 최대 클라이언트 수
max-clients 10

# 권한 낮추기 (보안 강화)
user nobody
group nogroup

# 재시작 시 키 유지
persist-key
persist-tun

# 로그 설정
status /var/log/openvpn/openvpn-status.log
log-append /var/log/openvpn/openvpn.log
verb 3

# 명시적 종료 알림
explicit-exit-notify 1

로그 디렉토리 생성

sudo mkdir -p /var/log/openvpn
sudo chown nobody:nogroup /var/log/openvpn

5. 네트워크 설정

IP 포워딩 활성화

# sysctl 설정 편집
sudo nano /etc/sysctl.conf

# 다음 라인 주석 해제 또는 추가
net.ipv4.ip_forward=1

# 설정 적용
sudo sysctl -p

방화벽 설정 (UFW 사용 시)

# 기본 인터페이스 확인
ip route list default

# NAT 설정을 위한 before.rules 편집
sudo nano /etc/ufw/before.rules

# *nat 섹션을 파일 맨 위에 추가 (COMMIT 전)
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
# OpenVPN NAT 규칙 (eth0는 실제 인터페이스명으로 변경)
-A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
COMMIT

# UFW 포워딩 정책 변경
sudo nano /etc/default/ufw

# 다음 라인 수정
DEFAULT_FORWARD_POLICY="ACCEPT"

# OpenVPN 포트 허용
sudo ufw allow 1194/udp
sudo ufw allow OpenSSH

# UFW 재시작
sudo ufw disable
sudo ufw enable

방화벽 설정 (iptables 직접 사용 시)

# NAT 규칙 추가 (eth0는 실제 인터페이스명으로 변경)
sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

# OpenVPN 포트 허용
sudo iptables -A INPUT -p udp --dport 1194 -j ACCEPT

# 규칙 저장
sudo apt install iptables-persistent
sudo netfilter-persistent save

6. OpenVPN 서버 시작

서비스 시작 및 활성화

# OpenVPN 서버 시작
sudo systemctl start openvpn-server@server

# 부팅 시 자동 시작 설정
sudo systemctl enable openvpn-server@server

# 서비스 상태 확인
sudo systemctl status openvpn-server@server
ubuntu@ip-172-31-32-24:~/openvpn-ca$ sudo systemctl status openvpn@server
● openvpn@server.service - OpenVPN connection to server
Loaded: loaded (/usr/lib/systemd/system/openvpn@.service; enabled; preset: enabled)
Active: active (running) since Sun 2025-12-28 17:18:08 UTC; 10s ago
Docs: man:openvpn(8)
https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
https://community.openvpn.net/openvpn/wiki/HOWTO
Main PID: 2355 (openvpn)
Status: "Initialization Sequence Completed"
Tasks: 1 (limit: 10)
Memory: 1.4M (peak: 1.6M)
CPU: 18ms
CGroup: /system.slice/system-openvpn.slice/openvpn@server.service
└─2355 /usr/sbin/openvpn --daemon ovpn-server --status /run/openvpn/server.status 10 --cd /etc/openvpn --script-security 2 --config /etc/openvpn/server.conf --writepid /run/openvpn/server.pid

로그 확인

# 실시간 로그 모니터링
sudo tail -f /var/log/openvpn/openvpn.log

# 시스템 로그 확인
sudo journalctl -u openvpn-server@server -f

네트워크 인터페이스 확인

# tun0 인터페이스 확인
ip addr show tun0

# 라우팅 테이블 확인
ip route

7. 클라이언트 인증서 생성

클라이언트 인증서 생성 스크립트

# Easy-RSA 디렉토리로 이동
cd ~/openvpn-ca

# 클라이언트 인증서 생성 (client1을 원하는 이름으로 변경)
./easyrsa gen-req client1 nopass

# 클라이언트 인증서 서명
./easyrsa sign-req client client1

# 클라이언트 파일 확인
ls pki/issued/client1.crt
ls pki/private/client1.key
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [client1]:ㅇ demo1

Notice
------
Private-Key and Public-Certificate-Request files created.
Your files are:
* req: /home/ubuntu/openvpn-ca/pki/reqs/client1.req
* key: /home/ubuntu/openvpn-ca/pki/private/client1.key

Using Easy-RSA 'vars' configuration:
* /home/ubuntu/openvpn-ca/vars

Using SSL:
* openssl OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024)
You are about to sign the following certificate:
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.
Request subject, to be signed as a client certificate
for '825' days:

subject=
commonName = demo1

Type the word 'yes' to continue, or any other input to abort.
Confirm request details: ㅛyes

Using configuration from /home/ubuntu/openvpn-ca/pki/openssl-easyrsa.cnf
Enter pass phrase for /home/ubuntu/openvpn-ca/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'demo1'
Certificate is to be certified until Apr 1 17:20:09 2028 GMT (825 days)

Write out database with 1 new entries
Database updated

Notice
------
Certificate created at:
* /home/ubuntu/openvpn-ca/pki/issued/client1.crt

클라이언트 설정 디렉토리 생성

# 클라이언트 설정 디렉토리 생성
mkdir -p ~/client-configs/files

# 베이스 설정 파일 생성
nano ~/client-configs/base.conf

클라이언트 베이스 설정 (base.conf)

client
dev tun
proto udp

# 서버 주소와 포트 (YOUR_SERVER_IP를 실제 IP로 변경)
remote YOUR_SERVER_IP 1194

resolv-retry infinite
nobind

# 권한 낮추기
user nobody
group nogroup

persist-key
persist-tun

# 인증서 확인
remote-cert-tls server

cipher AES-256-GCM
auth SHA256

key-direction 1

verb 3

클라이언트 설정 생성 스크립트

# 설정 생성 스크립트 작성
nano ~/client-configs/make_config.sh
#!/bin/bash

# 첫 번째 인자: 클라이언트 이름
KEY_DIR=~/openvpn-ca/pki
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}/issued/${1}.crt \
<(echo -e '</cert>\n<key>') \
${KEY_DIR}/private/${1}.key \
<(echo -e '</key>\n<tls-auth>') \
~/openvpn-ca/ta.key \
<(echo -e '</tls-auth>') \
> ${OUTPUT_DIR}/${1}.ovpn
# 실행 권한 부여
chmod +x ~/client-configs/make_config.sh

# 클라이언트 설정 파일 생성
cd ~/client-configs
./make_config.sh client1

# 생성된 파일 확인
ls ~/client-configs/files/

8. 클라이언트 연결

Linux 클라이언트

# OpenVPN 클라이언트 설치
sudo apt install openvpn

# 설정 파일로 연결
sudo openvpn --config client1.ovpn

# 백그라운드 서비스로 실행
sudo cp client1.ovpn /etc/openvpn/client/
sudo systemctl start openvpn-client@client1
sudo systemctl enable openvpn-client@client1
sudo journalctl -u openvpn@server -f
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: TCP connection established with [AF_INET]180.229.206.205:56590
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 TLS: Initial packet from [AF_INET]180.229.206.205:56590, sid=09a1036e 53265092
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 VERIFY OK: depth=1, CN=Easy-RSA CA
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 VERIFY OK: depth=0, CN=demo1
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 peer info: IV_VER=3.11.3
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 peer info: IV_PLAT=mac
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 peer info: IV_NCP=2
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 peer info: IV_TCPNL=1
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 peer info: IV_PROTO=8094
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 peer info: IV_MTU=1600
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 peer info: IV_CIPHERS=AES-128-CBC:AES-192-CBC:AES-256-CBC:AES-128-GCM:AES-192-GCM:AES-256-GCM:CHACHA20-POLY1305
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 peer info: IV_AUTO_SESS=1
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 peer info: IV_GUI_VER=OCmacOS_3.8.1-5790
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 peer info: IV_SSO=webauth,crtext
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 TLS: move_session: dest=TM_ACTIVE src=TM_INITIAL reinit_src=1
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 TLS: tls_multi_process: initial untrusted session promoted to trusted
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, peer certificate: 2048 bits RSA, signature: RSA-SHA256, peer temporary key: 253 bits X25519
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: 180.229.206.205:56590 [demo1] Peer Connection Initiated with [AF_INET]180.229.206.205:56590
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: demo1/180.229.206.205:56590 MULTI_sva: pool returned IPv4=10.8.0.6, IPv6=(Not enabled)
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: demo1/180.229.206.205:56590 MULTI: Learn: 10.8.0.6 -> demo1/180.229.206.205:56590
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: demo1/180.229.206.205:56590 MULTI: primary virtual IP for demo1/180.229.206.205:56590: 10.8.0.6
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: demo1/180.229.206.205:56590 SENT CONTROL [demo1]: 'PUSH_REPLY,redirect-gateway def1 bypass-dhcp,dhcp-option DNS 8.8.8.8,route 10.8.0.1,topology net30,ping 10,ping-restart 120,ifconfig 10.8.0.6 10.8.0.5,peer-id 0,cipher AES-256-GCM,protocol-flags cc-exit tls-ekm dyn-tls-crypt,tun-mtu 1500' (status=1)
Dec 28 18:33:20 ip-172-31-32-24 ovpn-server[2692]: demo1/180.229.206.205:56590 PUSH: Received control message: 'PUSH_REQUEST'
Dec 28 18:33:21 ip-172-31-32-24 ovpn-server[2692]: demo1/180.229.206.205:56590 Data Channel: cipher 'AES-256-GCM', peer-id: 0
Dec 28 18:33:21 ip-172-31-32-24 ovpn-server[2692]: demo1/180.229.206.205:56590 Timers: ping 10, ping-restart 240
Dec 28 18:33:21 ip-172-31-32-24 ovpn-server[2692]: demo1/180.229.206.205:56590 Protocol options: protocol-flags cc-exit tls-ekm dyn-tls-crypt

Windows 클라이언트

  1. OpenVPN GUI 다운로드 및 설치
  2. client1.ovpn 파일을 C:\Program Files\OpenVPN\config\ 디렉토리에 복사
  3. OpenVPN GUI 실행 후 연결

macOS 클라이언트

  1. Tunnelblick 다운로드 및 설치
  2. client1.ovpn 파일을 더블클릭하여 Tunnelblick에 추가
  3. Tunnelblick에서 연결

Android/iOS

  1. 앱스토어에서 “OpenVPN Connect” 설치
  2. client1.ovpn 파일을 기기로 전송
  3. 앱에서 파일 가져오기 후 연결

9. 연결 확인 및 문제 해결

서버에서 연결 확인

# 연결된 클라이언트 확인
sudo cat /var/log/openvpn/openvpn-status.log

# 실시간 연결 모니터링
sudo tail -f /var/log/openvpn/openvpn-status.log

클라이언트에서 연결 확인

# VPN IP 확인
ip addr show tun0

# VPN을 통한 라우팅 확인
ip route

# 외부 IP 확인 (VPN 서버 IP가 나와야 함)
curl ifconfig.me

일반적인 문제 해결

연결이 안 될 때

# 방화벽 상태 확인
sudo ufw status
sudo iptables -L -n -v

# OpenVPN 서비스 상태 확인
sudo systemctl status openvpn-server@server

# 로그 확인
sudo journalctl -u openvpn-server@server -n 50

IP 포워딩 확인

# IP 포워딩 활성화 여부 확인
cat /proc/sys/net/ipv4/ip_forward
# 1이어야 함

# 재설정
sudo sysctl -w net.ipv4.ip_forward=1

DNS 문제

# 클라이언트 설정 파일에 DNS 푸시 추가
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 1.1.1.1"

10. 보안 강화

강력한 암호화 설정

# server.conf에 추가
cipher AES-256-GCM
auth SHA512
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256

인증서 폐기 (CRL)

# 클라이언트 인증서 폐기
cd ~/openvpn-ca
./easyrsa revoke client1
./easyrsa gen-crl

# CRL 파일 복사
sudo cp ~/openvpn-ca/pki/crl.pem /etc/openvpn/server/

# server.conf에 추가
crl-verify crl.pem

Fail2ban 설정

# Fail2ban 설치
sudo apt install fail2ban

# OpenVPN 필터 생성
sudo nano /etc/fail2ban/filter.d/openvpn.conf
[Definition]
failregex = ^.*TLS Error: TLS key negotiation failed to occur within.*<HOST>
^.*Connection reset, restarting.*<HOST>
^.*TLS handshake failed.*<HOST>
ignoreregex =
# Jail 설정
sudo nano /etc/fail2ban/jail.local
[openvpn]
enabled = true
port = 1194
protocol = udp
filter = openvpn
logpath = /var/log/openvpn/openvpn.log
maxretry = 3
bantime = 600
# Fail2ban 재시작
sudo systemctl restart fail2ban
sudo fail2ban-client status openvpn

11. 성능 최적화

압축 설정

# server.conf와 client.conf에 추가
# 압축은 VORACLE 공격 위험이 있으므로 주의
compress lz4-v2
push "compress lz4-v2"

TCP 최적화 (UDP 사용 시 불필요)

# TCP 사용 시 성능 향상
tcp-nodelay

MTU 최적화

# 최적 MTU 값 찾기 (클라이언트에서)
ping -M do -s 1472 vpn_server_ip

# server.conf에 추가
tun-mtu 1500
mssfix 1450

12. 모니터링 및 로깅

상태 파일 모니터링

# 연결 상태 주기적으로 확인
watch -n 5 'sudo cat /var/log/openvpn/openvpn-status.log'

대역폭 모니터링

# iftop 설치
sudo apt install iftop

# tun0 인터페이스 모니터링
sudo iftop -i tun0

로그 레벨 조정

# server.conf에서 로그 레벨 설정
verb 3 # 0-11, 3이 기본값 (권장)

13. 백업 및 복구

중요 파일 백업

# 백업할 파일 목록
# - /etc/openvpn/server/*
# - ~/openvpn-ca/pki/*
# - /etc/sysctl.conf
# - /etc/ufw/before.rules (UFW 사용 시)

# 백업 스크립트
tar -czf openvpn-backup-$(date +%Y%m%d).tar.gz \
/etc/openvpn/server/ \
~/openvpn-ca/pki/ \
/etc/sysctl.conf \
/etc/ufw/before.rules

14. 고급 설정

특정 서브넷만 VPN으로 라우팅

# 클라이언트 설정에서 redirect-gateway 제거하고
# 특정 네트워크만 라우팅
route 192.168.1.0 255.255.255.0
route 10.0.0.0 255.255.255.0

클라이언트별 고정 IP 할당

# 클라이언트 설정 디렉토리 생성
sudo mkdir /etc/openvpn/ccd

# server.conf에 추가
client-config-dir ccd

# 클라이언트별 설정
sudo nano /etc/openvpn/ccd/client1
ifconfig-push 10.8.0.100 255.255.255.0

클라이언트에서 서버 LAN 접근

# server.conf에 추가 (192.168.1.0은 서버 LAN 서브넷)
push "route 192.168.1.0 255.255.255.0"

# 서버 방화벽에서 포워딩 허용
sudo iptables -A FORWARD -i tun0 -o eth0 -s 10.8.0.0/24 -d 192.168.1.0/24 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o tun0 -s 192.168.1.0/24 -d 10.8.0.0/24 -j ACCEPT

참고 자료

Share