Computer >> 컴퓨터 >  >> 시스템 >> Linux

CentOS/RHEL 리눅스에서 OpenVPN 서버 설치 및 구성하기

이 글에서는 리눅스 CentOS/RHEL(7/8) 환경에서 OpenVPN 서버를 설치하고 구성하는 전 과정을 다룹니다. 또한 NAT 뒤에 있는 두 대의 원격 컴퓨터(또는 지사)를 하나의 네트워크로 연결하는 방법과, 인증서 기반의 VPN 클라이언트 인증 절차까지 단계별로 소개합니다.

VPN(Virtual Private Network)은 공용 네트워크나 인터넷 위에 안전한 사설 네트워크를 구축할 수 있게 해주는 기술 모음입니다. VPN을 활용하면 서로 다른 장치나 네트워크를 인터넷을 통해 하나의 안전한 로컬 네트워크로 묶을 수 있습니다.

OpenVPN은 OpenSSL 기반의 SSL/TLS 방식 오픈소스 VPN 구현체 중 하나입니다. OpenVPN을 사용하면 원격 지사뿐 아니라 NAT 장비 뒤에 있는 개별 컴퓨터까지 하나의 네트워크로 통합할 수 있습니다.

1. OpenVPN 및 Easy-RSA 설치

먼저 EPEL 저장소를 연결하고 시스템을 최신 상태로 업데이트합니다.

# yum install epel-release -y
# yum update -y

시스템 업데이트가 끝나면 yum 패키지 관리자를 사용해 OpenVPNEasy-RSA를 설치합니다. Easy-RSA는 VPN 서버에서 PKI(공개 키 기반 구조)를 구축하는 데 필요한 도구입니다.

# yum install openvpn easy-rsa -y

2. Easy-RSA 구성 및 X.509 인증서 생성 방법

모든 easy-rsa 스크립트를 /etc/openvpn/ 디렉터리로 복사합니다.

# cp -r /usr/share/easy-rsa /etc/openvpn/

/etc/openvpn/easy-rsa/3/ 디렉터리로 이동한 후 vars 파일을 생성합니다.

# cd /etc/openvpn/easy-rsa/3/
# nano vars

아래 내용을 파일에 추가합니다(환경에 맞게 수정 가능).

set_var EASYRSA "$PWD"
set_var EASYRSA_PKI "$EASYRSA/pki"
set_var EASYRSA_DN "cn_only"
set_var EASYRSA_REQ_COUNTRY "DE"
set_var EASYRSA_REQ_PROVINCE "MUN"
set_var EASYRSA_REQ_CITY "BY"
set_var EASYRSA_REQ_ORG "WOSHUB"
set_var EASYRSA_REQ_EMAIL "vpnadmin@woshub.com"
set_var EASYRSA_REQ_OU "IT dept"
set_var EASYRSA_KEY_SIZE 4096
set_var EASYRSA_ALGO rsa
set_var EASYRSA_CA_EXPIRE 7500
set_var EASYRSA_CERT_EXPIRE 3650
set_var EASYRSA_NS_SUPPORT "no"
set_var EASYRSA_NS_COMMENT "CERTIFICATE AUTHORITY"
set_var EASYRSA_EXT_DIR "$EASYRSA/x509-types"
set_var EASYRSA_SSL_CONF "$EASYRSA/openssl-1.0.cnf"
set_var EASYRSA_DIGEST "sha512"

파일에 입력하는 조직 정보 등은 서버 동작에 영향을 주지 않으므로 자유롭게 지정할 수 있습니다. 파일은 실행 권한이 필요하므로 아래 명령을 실행합니다.

# chmod +x vars

3. OpenVPN 인증서 및 키 생성

키를 만들기 전에 먼저 PKI 디렉터리를 초기화하고 CA 키를 생성해야 합니다.

# cd /etc/openvpn/easy-rsa/3/
# ./easyrsa init-pki

Note: using Easy-RSA configuration from: ./vars
init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /etc/openvpn/easy-rsa/3/pki

CA 키를 생성합니다.

# ./easyrsa build-ca

명령 실행 후 키와 인증서 생성에 사용할 암호를 입력해야 합니다. 이 암호는 이후 인증서 서명 시에도 필요하므로 안전하게 보관하세요.

다음으로 서버 키를 생성합니다(서버 이름은 vpn.woshub.com). nopass 옵션은 암호 입력을 생략하는 옵션입니다.

# ./easyrsa gen-req vpn.woshub.com nopass

Note: using Easy-RSA configuration from: ./vars
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017
Generating a 4096 bit RSA private key
.........................++
writing new private key to '/etc/openvpn/easy-rsa/3/pki/private/vpn.woshub.com.key.R4IYCbD1zP'
-----
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) [vpn.woshub.com]:
Keypair and certificate request completed. Your files are:
req: /etc/openvpn/easy-rsa/3/pki/reqs/vpn.woshub.com.req
key: /etc/openvpn/easy-rsa/3/pki/private/vpn.woshub.com.key

인증서 발급 과정에서 Common Name 항목에는 그대로 Enter 키를 누르면 됩니다.

생성된 vpn.woshub.com 키를 CA 인증서로 서명합니다.

# ./easyrsa sign-req server vpn.woshub.com

서명 시에는 CA 인증서 발급 때 설정했던 암호가 필요하며, 진행 중 확인 메시지에는 yes를 입력합니다.

인증서가 오류 없이 정상적으로 생성되었는지 확인하려면 아래 명령을 실행합니다.

# openssl verify -CAfile pki/ca.crt pki/issued/vpn.woshub.com.crt

pki/issued/vpn.woshub.com.crt: OK

이제 OpenVPN 서버에 필요한 인증서가 모두 준비되었습니다.

  • 루트 인증서: pki/ca.crt
  • 서버 개인 키: pki/private/vpn.woshub.com.key
  • 서버 인증서: pki/issued/vpn.woshub.com.crt

클라이언트 키를 생성하려면 아래 명령을 실행합니다.

# ./easyrsa gen-req client_name nopass

예시로 admin1 클라이언트 키를 생성해 보겠습니다.

# ./easyrsa gen-req admin1 nopass

Note: using Easy-RSA configuration from: ./vars
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017
Generating a 4096 bit RSA private key
..........++
writing new private key to '/etc/openvpn/easy-rsa/3/pki/private/admin1.key.R5OY6reT2e'
-----
Common Name (eg: your user, host, or server name) [admin1]:
Keypair and certificate request completed. Your files are:
req: /etc/openvpn/easy-rsa/3/pki/reqs/admin1.req
key: /etc/openvpn/easy-rsa/3/pki/private/admin1.key

서버 키와 마찬가지로 클라이언트 키도 CA 인증서로 서명해야 합니다.

# ./easyrsa sign-req client admin1

이제 사용자용 인증서가 생성되었습니다. 추가로 키 교환에 사용할 Diffie-Hellman 키를 생성합니다.

# ./easyrsa gen-dh

DH 키 생성은 다소 시간이 걸릴 수 있습니다. 이어서 TLS 인증서도 생성합니다.

# openvpn --genkey --secret ta.key

나중에 클라이언트 인증서를 폐기(revoke)할 수 있도록 CRL 키도 미리 생성해 둡니다.

# ./easyrsa gen-crl

Note: using Easy-RSA configuration from: ./vars
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017
Using configuration from /etc/openvpn/easy-rsa/3/pki/safessl-easyrsa.cnf
Enter pass phrase for /etc/openvpn/easy-rsa/3/pki/private/ca.key:
An updated CRL has been created.
CRL file: /etc/openvpn/easy-rsa/3/pki/crl.pem

인증서를 폐기해야 할 때는 아래 명령을 사용합니다(admin1은 인증서 이름).

./easyrsa revoke admin1

필요한 인증서가 모두 준비되었으면 작업 디렉터리로 복사합니다. 먼저 서버 인증서입니다.

# cp pki/ca.crt /etc/openvpn/server/
# cp pki/issued/vpn.woshub.com.crt /etc/openvpn/server/
# cp pki/private/vpn.woshub.com.key /etc/openvpn/server/
# cp pki/private/dh.pem /etc/openvpn/server/
# cp pki/private/ta.key /etc/openvpn/server/
# cp pki/crl.pem /etc/openvpn/server/

다음은 클라이언트 인증서입니다.

# cp pki/issued/admin1.crt /etc/openvpn/client/
# cp pki/private/admin1.key /etc/openvpn/client/

4. OpenVPN 서버 설정 파일 및 방화벽 규칙

이제 OpenVPN 설정 파일을 작성합니다. 먼저 server.conf 파일을 생성합니다.

# cd /etc/openvpn/ && nano server.conf

파일 내용을 아래와 같이 작성합니다.

# 포트, 프로토콜, 디바이스 지정
port 1194
proto udp
dev tun
# 서버 인증서 경로 지정
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/vpn.woshub.com.crt
key /etc/openvpn/server/vpn.woshub.com.key
# CRL 및 DH 키 경로
dh /etc/openvpn/server/dh.pem
crl-verify /etc/openvpn/server/crl.pem
# VPN 클라이언트에 할당할 네트워크 IP 대역
server 10.1.2.0 255.255.255.0
push "redirect-gateway def1"
# 클라이언트에 할당할 DNS 서버
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
# 동일 키를 사용하는 여러 클라이언트 접속 허용
duplicate-cn
# TLS 보호 설정
tls-auth /etc/openvpn/server/ta.key 0
cipher AES-256-CBC
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA256
auth SHA512
auth-nocache
# 기타 설정 항목
keepalive 20 60
persist-key
persist-tun
comp-lzo yes
daemon
user nobody
group nobody
# 로그 파일 경로
log-append /var/log/openvpn.log
verb 3

파일을 저장합니다. 여기서는 기본 UDP 포트인 1194를 사용했지만, 서버에서 사용 중이지 않은 임의의 포트를 지정해도 됩니다.

이제 세그먼트 간 연결과 라우팅을 허용하도록 방화벽 규칙만 설정하면 됩니다.

firewalld를 사용하는 경우, 먼저 커널의 포워딩 모듈을 활성화합니다.

# echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf
# sysctl -p

net.ipv4.ip_forward = 1

firewalld에 openvpn 서비스를 추가하고, tun0 인터페이스를 trusted 존에 등록합니다.

# firewall-cmd --permanent --add-service=openvpn
# firewall-cmd --permanent --zone=trusted --add-interface=tun0

trusted 존에 MASQUERADE를 활성화합니다.

# firewall-cmd --permanent --zone=trusted --add-masquerade

NAT를 활성화합니다.

# firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s 10.1.2.0/24 -o Server_IP -j MASQUERADE
# firewall-cmd –reload

firewalld 없이 iptables만 사용하는 경우에는 아래 명령을 실행합니다.

# iptables -t nat -A POSTROUTING -s 10.1.2.0/24 -o eth0 -j MASQUERADE
# iptables -A INPUT -p udp –dport 1194 -j ACCEPT
# service iptables save

OpenVPN 서비스를 시작하고 부팅 시 자동 실행되도록 등록합니다.

# systemctl start openvpn@server
# systemctl enable openvpn@server

openvpn 서비스가 udp/1194 포트를 정상적으로 수신하고 있는지 확인합니다.

# lsof -i:1194

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
openvpn 12327 nobody 5u IPv4 45122 0t0 UDP *:openvpn

네트워크 인터페이스의 IP 설정도 확인해 봅니다.

# ip a

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
link/none
inet 10.1.2.1 peer 10.1.2.2/32 scope global tun0
valid_lft forever preferred_lft forever

설정 시 지정한 네트워크가 tun0 장치에 정상적으로 할당된 것을 확인할 수 있습니다. 지금까지의 설정만으로 OpenVPN이 동작할 준비가 완료되었습니다.

5. OpenVPN으로 여러 사무실(컴퓨터) 연결하기

이번에는 NAT 뒤에서 인터넷에 접속하는 두 대의 원격 컴퓨터가 OpenVPN 서버에 접속해 하나의 네트워크로 묶이는 과정을 살펴보겠습니다. Windows 환경에서는 OpenVPN 공식 클라이언트를 사용했습니다. 클라이언트는 공식 웹사이트에서 다운로드할 수 있으며, 설치 과정 설명은 생략하고 바로 구성 방법으로 넘어가겠습니다.

클라이언트 설치가 끝나면 아래 경로에서 설정 파일을 생성합니다.

C:\Program Files\OpenVPN\config\

여기서는 client라는 이름의 파일을 만들고 다음 내용을 추가했습니다.

client
dev tun
proto udp
remote 112.113.114.15 1194
resolv-retry infinite
nobind
block-outside-dns
persist-key
persist-tun
mute-replay-warnings
remote-cert-tls server
tls-client
auth SHA512
tls-auth "C:\\Program Files\\OpenVPN\\config\\ta.key" 1
remote-cert-eku "TLS Web Server Authentication"
ca "C:\\Program Files\\OpenVPN\\config\\ca.crt"
cert "C:\\Program Files\\OpenVPN\\config\\admin1.crt"
key "C:\\Program Files\\OpenVPN\\config\\admin1.key"
cipher AES-256-CBC
comp-lzo
verb 3

설정에는 앞서 생성한 클라이언트 인증서, 보안 키(ta.key), 서버 인증서가 필요합니다. 해당 파일들을 서버에서 내려받아 로컬 폴더에 저장한 뒤, 설정 파일에 각 파일의 경로를 지정하면 됩니다.

이후 트레이의 OpenVPN 아이콘을 클릭해 서버에 접속할 수 있습니다.

접속에 성공하면 첫 번째 PC는 다음과 같은 IP 주소를 받게 됩니다.

IPv4 address. . . . . . . . . . . . : 10.1.2.14
Subnet mask . . . . . . . . . . : 255.255.255.0

두 번째 NAT 뒤의 컴퓨터에서도 동일한 절차를 수행했습니다. 두 번째 사용자용 인증서는 미리 생성해 두었습니다. 접속 후 두 번째 PC 역시 VPN 네트워크에서 IP 주소를 할당받습니다.

IPv4 address. . . . . . . . . . . . : 10.1.2.16
Subnet mask . . . . . . . . . . : 255.255.255.0

접속이 완료되면 두 컴퓨터는 같은 네트워크에 속하게 되며 서로를 인식할 수 있습니다. 실제로 ping 테스트를 통해 확인해 보겠습니다.

두 번째 PC로 ping을 보낸 결과:

Pinging 10.1.2.16 with 32 bytes of data:
Reply from 10.1.2.16: bytes=32 time=73ms TTL=127

첫 번째 PC로 ping을 보낸 결과:

Pinging 10.1.2.14 with 32 bytes of data:
Reply from 10.1.2.14: bytes=32 time=79ms TTL=127

연결된 두 VPN 클라이언트는 서로 패킷을 주고받고 파일을 직접 전송할 수 있습니다. 이처럼 물리적으로 멀리 떨어진 두 장치를 하나의 로컬 네트워크로 통합할 수 있습니다.

OpenVPN 서버에서는 사용자별 키와 인증서를 무제한으로 생성할 수 있습니다. 새 인증서가 필요하면 /etc/openvpn/easy-rsa/3 디렉터리에서 아래 명령을 실행하세요.

# ./easyrsa gen-req clientname nopass
# ./easyrsa sign-req client clientname

마지막으로, 더 이상 사용하지 않는 클라이언트 인증서는 반드시 폐기하여 네트워크 보안을 유지하시기 바랍니다.