1. 개요

우선 OpenVPN은 기본적으로 서버의 시스템계정정보를 이용해 서버접속을 하도록 구성되어 있습니다. 서버내 계정이 1개만 존재하면 컨트롤하기 쉬우나, 호스팅서버이거나 계정이 많은 경우는 제어하기 힘든 부분이 있으므로, 별도의 계정을 만들어 제어하도록 합니다.

 

2. 설치방법

 

우선 참고로 한 사이트는
이며, 해당 페이지를 참조로 설치하며 오류가 나는 부분들은 수정해서 처리되었습니다.

# 필요 패키지 다운로드
cd /usr/local/src
wget skyfirewin.kr/DATA/OPENVPN/lzo-2.06.tar.gz
wget skyfirewin.kr/DATA/OPENVPN/openssl-1.0.1c.tar.gz
wget skyfirewin.kr/DATA/OPENVPN/openvpn-2.2.2.tar.gz
wget skyfirewin.kr/DATA/OPENVPN/pam-pam_pwdfile-0.99-2.i386.rpm
혹시 64bit 서버인 경우엔
wget skyfirewin.kr/DATA/OPENVPN/pam_pwdfile-0.99-1.puias6.x86_64.rpm

# openssl install
cd /usr/local/src
tar xzvf openssl-1.0.1c.tar.gz 
cd openssl-1.0.1c
./config --prefix=/usr/local/openssl
make ; make install

# lzo install
cd /usr/local/src
tar xzvf lzo-2.06.tar.gz 
cd lzo-2.06
./configure --prefix=/usr/local/lzo
make ; make install

# openvpn install
cd /usr/local/src
tar xzvf openvpn-2.2.2.tar.gz
cd openvpn-2.2.2

./configure --prefix=/usr/local/openvpn \
--with-lzo-lib=/usr/local/lzo/lib/ --with-lzo-headers=/usr/local/lzo/include/ \
--with-ssl-headers=/usr/local/openssl/include/ --with-ssl-lib=/usr/local/openssl/lib/

make ; make install

cp -r easy-rsa/ /usr/local/openvpn/
cd plugin/auth-pam
make
mkdir -p /usr/local/openvpn/lib
cp -a openvpn-auth-pam.so /usr/local/openvpn/lib/

# pam_pwdfile install
cd /usr/local/src
 
# 32bit 인경우
rpm -ivh pam-pam_pwdfile-0.99-2.i386.rpm
 
#64bit 인 경우
rpm -ivh pam_pwdfile-0.99-1.puias6.x86_64.rpm
 
echo "auth required pam_pwdfile.so pwdfile /usr/local/openvpn/auth_vpn/secrets/user" >> /etc/pam.d/vuser 
echo "account required pam_permit.so" >> /etc/pam.d/vuser

# Openvpn Key 생성 
cd /usr/local/openvpn/easy-rsa/2.0
ln -s openssl-1.0.0.cnf openssl.cnf



# var파일의 하단에 추가 
export KEY_COUNTRY=KR
export KEY_PROVINCE=NA
export KEY_CITY=SEOUL
export KEY_ORG="hanbiro"
export KEY_EMAIL=fireawll@hanbiro.com



# CA key/crt 생성 
source ./vars 
./clean-all
./build-ca
 

# var에 CA에 입력되는 정보를 사전에 export했으므로 CA생성시 엔터만 쳐주면 된다. 


# Server key/crt 생성 
./build-key-server server
Generating a 1024 bit RSA private key
.........................++++++
.............................++++++
writing new private key to 'server.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.
-----
Country Name (2 letter code) [KR]:
State or Province Name (full name) [NA]:
Locality Name (eg, city) [SEOUL]:
Organization Name (eg, company) [netggio]:
Organizational Unit Name (eg, section) []:system team
Common Name (eg, your name or your server's hostname) [server]:vpn server
Name []:
Email Address [vpn@netggio.pe.kr]: 

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /usr/local/openvpn/easy-rsa/2.0/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'KR'
stateOrProvinceName   :PRINTABLE:'NA'
localityName          :PRINTABLE:'SEOUL'
organizationName      :PRINTABLE:'netggio'
organizationalUnitName:PRINTABLE:'system team'
commonName            :PRINTABLE:'vpn server'
emailAddress          :IA5STRING:'vpn@netggio'
Certificate is to be certified until Jun 19 08:32:09 2022 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated 

# Diffie Hellman 생성
./build-dh 
Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time




# 사용할 Key 복사 
mkdir -p /usr/local/openvpn/auth_vpn/key
cp -a keys/*.crt /usr/local/openvpn/auth_vpn/key/
cp -a keys/*.key /usr/local/openvpn/auth_vpn/key/
cp -a keys/dh1024.pem /usr/local/openvpn/auth_vpn/key/



# VPN 서버의 OpenVpn 설정 

vpn설정들이 놓일 기본 위치 디렉 생성 


mkdir -p /usr/local/openvpn/auth_vpn/sbin 
mkdir -p /usr/local/openvpn/auth_vpn/log
 
mkdir -p /usr/local/openvpn/auth_vpn/secrets
 
mkdir -p /usr/local/openvpn/auth_vpn/client
 




# Openvpn conf 생성

파일 위치 -> /usr/local/openvpn/auth_vpn/auth_vpn.conf 
#/usr/local/openvpn/auth_vpn/auth_vpn.conf

local 172.0.0.100

## udp로 운영할 경우
port 5000
proto udp

## tcp로 운영할 경우 
#proto tcp-server
#port 1194 

dev tap0 

ca "/usr/local/openvpn/auth_vpn/key/ca.crt"
key "/usr/local/openvpn/auth_vpn/key/server.key"
cert "/usr/local/openvpn/auth_vpn/key/server.crt"
dh "/usr/local/openvpn/auth_vpn/key/dh1024.pem" 

server 10.0.3.0 255.255.255.0 
# 접속 후 86400 초 후 접속 끊김
keepalive 10 86400

comp-lzo

persist-key
 
# 접속 후 10800초 동안 동작이 없을 경우 접속 끊김
inactive 10800

ping-timer-rem

verb 5
plugin /usr/local/openvpn/lib/openvpn-auth-pam.so "/etc/pam.d/vuser"
client-config-dir /usr/local/openvpn/auth_vpn/client

script-security 3  system

client-cert-not-required
username-as-common-name
ccd-exclusive 

push "route 10.0.3.0 255.255.255.0"

client-connect /usr/local/openvpn/auth_vpn/sbin/client_start.pl
client-disconnect /usr/local/openvpn/auth_vpn/sbin/client_close.pl

status /usr/local/openvpn/auth_vpn/log/status-alex-vpn.log
log-append  /usr/local/openvpn/auth_vpn/log/alex-vpn.log


# client-connect 와 client-disconnect 는 현재 확인중에 있습니다.


# client_start.pl 생성

VPN유저가 로그인에 성공 하게 되면 작동하는 스크립트이고 로그인 시간을 별도로 남기는데 사용. /usr/local/openvpn/auth_vpn/sbin/client_start.pl 


#!/usr/bin/perl

# /usr/local/openvpn/auth_vpn/sbin/client_start.pl

use strict;
use warnings;
use POSIX qw/strftime/;
use Sys::Hostname;
use vars qw( $username $dev $untrusted_ip $ifconfig_pool_remote_ip );

$username = $ENV{'username'};
$dev = $ENV{'dev'};
$ifconfig_pool_remote_ip = $ENV{'ifconfig_pool_remote_ip'};
$untrusted_ip = $ENV{'untrusted_ip'};

my $YY=strftime('%Y',localtime);
my $MM=strftime('%m',localtime);
my $DD=strftime('%d',localtime);
my $HH=strftime('%H',localtime);
my $MIN=strftime('%M',localtime);
my $SS=strftime('%S',localtime); 

my $svr = hostname;

system "mkdir -p /usr/local/openvpn/auth_vpn/log/";

open (LOG, ">>/usr/local/openvpn/auth_vpn/log/vpn_access.log");
print LOG "VPN_Start_Time: $YY/$MM/$DD $HH:$MIN:$SS ID: $username Source_IP: $untrusted_ip Assigned_IP:$ifconfig_pool_remote_ip\n";
close (LOG);





# client_close.pl 생성

/usr/local/openvpn/auth_vpn/sbin/client_close.pl VPN유저가 로그오프 하게 되면 작동하는 스크립트이고 로그오프 시간을 별도로 남기는데 사용. 
#!/usr/bin/perl

# /usr/local/openvpn/auth_vpn/client_close.pl


use strict;
use warnings;
use Sys::Hostname;
use POSIX qw/strftime/;

use vars qw( $username $dev $trusted_ip $ifconfig_pool_remote_ip);


$username = $ENV{'username'};
$dev = $ENV{'dev'};
$ifconfig_pool_remote_ip = $ENV{'ifconfig_pool_remote_ip'};
$trusted_ip = $ENV{'trusted_ip'};

my $YY=strftime('%Y',localtime);
my $MM=strftime('%m',localtime);
my $DD=strftime('%d',localtime);
my $HH=strftime('%H',localtime);
my $MIN=strftime('%M',localtime);
my $SS=strftime('%S',localtime);

print "VPN_END_Time: $YY/$MM/$DD $HH:$MIN:$SS  ID: $username  Source_IP: $trusted_ip  Assigned_IP:$ifconfig_pool_remote_ip\n";

my $svr = hostname;

system "mkdir -p /usr/local/openvpn/auth_vpn/log/";

open (LOG, ">>/usr/local/openvpn/auth_vpn/log/vpn_access.log");
print LOG "VPN_END_Time: $YY/$MM/$DD $HH:$MIN:$SS  ID: $username  Source_IP: $trusted_ip  Assigned_IP:$ifconfig_pool_remote_ip\n";
close (LOG);

chmod 777 /usr/local/openvpn/auth_vpn/sbin/*.pl

# VPN Client 설치 및 설정 파일 
http://swupdate.openvpn.org/community/releases/ 에서 최근 버전 설치(윈도7 같은경우 구버전 사용시 문제 라우팅 문제 생길수 있으니 최신 버전 권장) 
VPN유저에게 배포되어야 할 사항 VPN유저에게는 서버에서 키 생성할때 만든 생성한 ca.crt 파일 -> VPN서버에서 생성한 인증서 ca.crt 를 C:\Program Files\OpenVPN\config 에 저장 
openvpn의 클라이이언트용 config파일 -> C:\Program Files\OpenVPN\config 폴더 아래에 내용을 auth_vpn_client.ovpn로 저장 
유저 계정정보 ( 계정 생성 ip할당은 아래 유저관리 부분 참고) 

client
dev tap
remote  172.0.0.100
proto udp
port 5000
nobind
ca ca.crt
persist-key
persist-tun
comp-lzo
auth-user-pass
verb 3
auth-nocache
mute 20


# VPN계정 관리/IP할당

아파치의 htpasswd를 이용해서 생성 하면 된다. (아파치 버전에 따라 htpasswd의 암호화 디폴트 값이 다르며, MD5방식으로 패스파일을 만들어줘야 인식 한다 -> 참조페이지상으로는 htpasswd -m 옵션을 이용해서 md5 로 구축해야 하지만 확인결과 CRYPT 모드인 htpasswd -d 로 생성해야 vpn 인증을 통과함.) 

# 계정 생성
touch /usr/local/openvpn/auth_vpn/secrets/user
chmod -R 400 /usr/local/openvpn/auth_vpn/secrets
htpasswd -d /usr/local/openvpn/auth_vpn/secrets/user hanbiro
New password: 
Re-type new password: 
Adding password for user hanbiro

# 계정 패스 변경
htpasswd -d /usr/local/openvpn/auth_vpn/secrets/user hanbiro


# 계정 삭제
htpasswd -D /usr/local/openvpn/auth_vpn/secrets/user hanbiro
Deleting password for user hanbiro


# 유저의 IP 할당
위에 계정 생성한 ID명으로 /usr/local/openvpn/auth_vpn/client/ 하위에 파일을 생성해주면 끝난다. 
유저의 계정 삭제시 생성한 파일을 삭제 해주면 된다. 

cat /usr/local/openvpn/auth_vpn/client/hanbiro
ifconfig-push 10.0.3.4 255.255.255.0  # hanbiro id가 사용할 ip를 적어 주면 된다. 
push route 10.0.3.0 255.255.255.0       # 유저별로 별도의 라우팅을 넣어주고 싶을때 사용한다.
 
위 설정은 id 당 1 개의 접근만 허용할때 사용하며 다중접속시에는 ipconfig-push 설정을 해제해야 한다.
 
# openvpn 구동스크립트
cat /root/openvpn_htpasswd_start.sh
#!/bin/sh
/usr/local/openvpn/sbin/openvpn --config /usr/local/openvpn/auth_vpn/auth_vpn.conf --duplicate-cn --mode server --daemon

 

========================================================

클라이언트측에서 무작위로 연결 끊김 현상이 발견되어 로그 확인 결과
TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)
TLS Error: TLS handshake failed

와 같은 로그가 발생됩니다.
Server/Client 방식에서는 발견되지 않던 문제라
client.ovpn 파일 내용을

client
dev tap
remote 172.0.0.100
proto udp
port 5000
nobind
tls-client
ca ca.crt
cert server.crt
key openvpn.key
comp-lzo
auth-user-pass
verb 3
auth-nocache
mute 20

로 변경 확인중입니다.

============================================================