Hướng dẫn cài đặt OpenVPN trên CentOS 7 từ A-Z

Giới thiệu

Rất nhiều bài hướng dẫn trên mạng hướng dẫn bạn cách cài đặt openVPN rồi, hôm nay thông qua tuts này mình cũng không nói nhiều đến lý thuyết nữa mà sẽ hướng dẫn bạn cài đặt và cấu hình OpenVPN trên CentOS 7 với easy-rsa 3 + một script nho nhỏ bằng bash để bạn tiện managed user mình tạo ra.

P/s: Lý thuyết sure là mình sẽ viết một bài riêng để nói về cách làm việc của openVPN =)))

Cài đặt OpenVPN với easy-rsa 3

Cài các package cần thiết:

yum install epel* -y
yum install openvpn pam-devel lzo-devel openssl openssl-devel -y

Đi đến thư mục /etc/openvpn/ bạn clone easy-rsa 3 về:

git clone https://github.com/OpenVPN/easy-rsa

Bạn chỉ giữ lại thư mục easyrsa3 thôi nhen còn lại có thể xóa tùy ý, cd tiếp vào bên trong thư mục này và làm theo các step sau để khởi tạo  CA và server certificate:

#step 1 move file
mv vars.example vars

#step 2 build the CA
./easyrsa init-pki
./easyrsa build-ca nopass

#step 3 - build the DH key
./easyrsa gen-dh

#Step 4 - Generate the OpenVPN server certificate/key 
./easyrsa gen-req server nopass
./easyrsa sign-req server server

#(Optional) Step 5 - Create static secret 
openvpn --genkey --secret ta.key

Để tạo user chứng thực khi quay VPN:

./easyrsa gen-req client1 nopass
./easyrsa sign-req client client1
##(client1 là tên user)

Để revoke user trong trường hợp staff quit khỏi công ty hoặc vì lý do nào khác:

./easyrsa --batch revoke $CLIENT
./easyrsa gen-crl
rm -rf pki/reqs/$CLIENT.req
rm -rf pki/private/$CLIENT.key
rm -rf pki/issued/$CLIENT.crt

Tiếp đến là phần cấu hình OpenVPN, bạn hãy copy các key khi tạo ở bước trên (bao gồm ca và server certificate) ra ngoài thư mục gốc của openVPN:

cp pki/ca.crt /etc/openvpn
cp pki/issued/server.crt /etc/openvpn/
cp pki/private/server.key /etc/openvpn/
cp pki/dh.pem /etc/openvpn/
cp ta.key /etc/openvpn/

Đứng tại thư mục /etc/openvpn, bạn tạo file server.conf với template mẫu như sau (đây là option của mình, bạn có thể điều chỉnh lại theo yêu cầu riêng của mình):

local 0.0.0.0

port 11194

# TCP or UDP server?
;proto tcp
proto udp

;dev tap
dev tun

ca /etc/openvpn/ca.crt
cert /etc/openvpn/server.crt
key /etc/openvpn/server.key

dh /etc/openvpn/dh.pem


server 10.20.0.0 255.255.255.0
ifconfig 10.20.0.1 10.20.0.2

ifconfig-pool-persist ipp.txt


push "route 10.20.0.1 255.255.255.255"
push "route 10.20.0.0 255.255.255.0"
push "route 172.17.1.0 255.255.255.0"
push "route 172.17.2.0 255.255.255.0"

client-config-dir ccd

#push "redirect-gateway def1" ##option này bạn có thể sử dụng nếu muốn toàn bộ network route đến IP openVPN server, còn nếu bỏ đi thì nó chỉ route qua IP openVPN server khi bạn truy cập đến các subnet trong option "púhh route ..."

push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"

;client-to-client
duplicate-cn

keepalive 10 120

tls-auth /etc/openvpn/ta.key 0 # This file is secret

cipher AES-256-CBC

;compress lz4-v2
;push "compress lz4-v2"

;comp-lzo

;max-clients 100

persist-key
persist-tun

status openvpn-status.log

verb 3

explicit-exit-notify 1
log /var/log/openvpn.log
plugin /usr/lib64/openvpn/plugins/openvpn-plugin-auth-pam.so login

Đây là các option cơ bản, bạn có thể lấy mẫu và đọc mô tả từng chức năng của các option tại path: /usr/share/doc/openvpn-2.4.7/sample/sample-config-files/server.conf

Cụ thể với mục đích của mình là route thông qua IP openVPN đến các subnet: 172.17.1.0/24, 172.17.2.0/24, 10.20.0.0/24, 10.20.0.1.

Các truy cập không qua các subnet này sẽ route trực tiếp thông qua IP nơi bạn truy cập.

Mình sử dụng xác thực bằng PAM, nên khi tạo xong user VPN, bạn tạo user tuơng tự trên OS và đặt password cho nó:

useradd {username}
passwd {username}

enable route trên CentOS 7:

vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
sysctl -p

Khởi động và enable service:

systemctl start openvpn@server
systemctl enable openvpn@server

Mở rule cho iptables:

iptables -A FORWARD -i eth0 -o tun0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -s 10.20.0.0/24 -o eth0 -j ACCEPT
sudo iptables -t nat -A POSTROUTING -s 10.20.0.0/24 -o eth0 -j MASQUERADE

Hoặc bạn có thể tạo 1 script nhỏ để chạy khi server lỡ reboot (vì mình chưa cài iptables service mà chỉ có file rule nên mỗi lần reboot sẽ mất rule)

vim iproute.sh
###############################################################################
# Copy the section below on the script iproute.sh
###############################################################################
#!/bin/sh
# chkconfig: 345 99 10
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
#sudo iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
iptables -A FORWARD -i eth0 -o tun0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -s 10.20.0.0/24 -o eth0 -j ACCEPT
sudo iptables -t nat -A POSTROUTING -s 10.20.0.0/24 -o eth0 -j MASQUERADE
###############################################################################

Hoặc cài iptables service vào để lưu được rule khi reboot lại:

systemctl stop firewalld
systemctl disable firewalld
systemctl mask firewalld

yum install iptables-services -y
systemctl start iptables
systemctl enable iptables

iptables -A FORWARD -i eth0 -o tun0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -s 10.20.0.0/24 -o eth0 -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.20.0.0/24 -o eth0 -j MASQUERADE

iptabes-save > /etc/sysconfig/iptables

Lấy key về máy để quay VPN

Xong config trên server rồi, khi nãy bạn đã tạo user là client1 rồi đúng không nào (nhớ tạo user PAM tuơng ứng nhé). Lấy các file sau về máy local: ca.crt, client1.crt, client1.key, ta.key

đặt chúng trong cùng một thư mục, tạo 1 file tên là client1.ovpn, bạn mở file và thêm vào các option sau:

client
dev tun
proto udp
remote {IP VPN server} 11194
resolv-retry 10
nobind
persist-key
persist-tun
verb 3

tun-mtu 1500
tun-mtu-extra 32
mssfix 1440
cipher AES-256-CBC

ca ca.crt
cert client1.crt
key client1.key
key-direction 1
remote-cert-tls server
tls-auth ta.key 1
auth-user-pass
auth-nocache

done!!

Trên windows bạn cài openVPN GUI, đặt toàn bộ file config vào thư mục “C:\Program Files\OpenVPN\config\”

Trên Linux thì đặt đâu cũng được, miễn toàn bộ các file cùng nằm trong 1 thư mục =)))

Quay VPN trên Linux:

sudo openvpn --config client1.ovpn

nhập user, password vào, nếu thấy kết quả trả về “Initialization Sequence Completed” là thành công, bạn test lại bằng lệnh “route -n”

tritran@tritran-Latitude-E6540:~/Desktop$ sudo openvpn --config client.ovpn 
Tue Oct 22 23:42:01 2019 OpenVPN 2.4.4 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on May 14 2019
Tue Oct 22 23:42:01 2019 library versions: OpenSSL 1.1.1  11 Sep 2018, LZO 2.08
Enter Auth Username: test1
Enter Auth Password: ***********
Tue Oct 22 23:42:07 2019 WARNING: No server certificate verification method has been enabled.  See http://openvpn.net/howto.html#mitm for more info.
Tue Oct 22 23:42:07 2019 Outgoing Control Channel Authentication: Using 160 bit message hash 'SHA1' for HMAC authentication
Tue Oct 22 23:42:07 2019 Incoming Control Channel Authentication: Using 160 bit message hash 'SHA1' for HMAC authentication
Tue Oct 22 23:42:07 2019 TCP/UDP: Preserving recently used remote address: [AF_INET]115.77.191.44:1195
Tue Oct 22 23:42:07 2019 Socket Buffers: R=[212992->212992] S=[212992->212992]
Tue Oct 22 23:42:07 2019 UDP link local: (not bound)
Tue Oct 22 23:42:07 2019 UDP link remote: [AF_INET]115.77.191.44:1195
Tue Oct 22 23:42:07 2019 TLS: Initial packet from [AF_INET]115.77.191.44:1195, sid=ccd53754 28517291
Tue Oct 22 23:42:07 2019 WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this
Tue Oct 22 23:42:08 2019 VERIFY OK: depth=1, CN=ebuynow
Tue Oct 22 23:42:08 2019 VERIFY OK: depth=0, CN=./easyrsa sign-req server servercinatic
Tue Oct 22 23:42:08 2019 WARNING: 'link-mtu' is used inconsistently, local='link-mtu 1589', remote='link-mtu 1557'
Tue Oct 22 23:42:08 2019 WARNING: 'tun-mtu' is used inconsistently, local='tun-mtu 1532', remote='tun-mtu 1500'
Tue Oct 22 23:42:08 2019 Control Channel: TLSv1.2, cipher TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384, 2048 bit RSA
Tue Oct 22 23:42:08 2019 [./easyrsa sign-req server servercinatic] Peer Connection Initiated with [AF_INET]115.77.191.44:1195
Tue Oct 22 23:42:09 2019 SENT CONTROL [./easyrsa sign-req server servercinatic]: 'PUSH_REQUEST' (status=1)
Tue Oct 22 23:42:09 2019 PUSH: Received control message: 'PUSH_REPLY,route 10.20.0.0 255.255.255.0,route 172.16.1.0 255.255.0.0,redirect-gateway def1,dhcp-option DNS 8.8.8.8,dhcp-option DNS 8.8.4.4,route 10.20.0.1,topology net30,ping 10,ping-restart 120,ifconfig 10.20.0.10 10.20.0.9,peer-id 1,cipher AES-256-GCM'
Tue Oct 22 23:42:09 2019 OPTIONS IMPORT: timers and/or timeouts modified
Tue Oct 22 23:42:09 2019 OPTIONS IMPORT: --ifconfig/up options modified
Tue Oct 22 23:42:09 2019 OPTIONS IMPORT: route options modified
Tue Oct 22 23:42:09 2019 OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified
Tue Oct 22 23:42:09 2019 OPTIONS IMPORT: peer-id set
Tue Oct 22 23:42:09 2019 OPTIONS IMPORT: adjusting link_mtu to 1656
Tue Oct 22 23:42:09 2019 OPTIONS IMPORT: data channel crypto options modified
Tue Oct 22 23:42:09 2019 Data Channel: using negotiated cipher 'AES-256-GCM'
Tue Oct 22 23:42:09 2019 Outgoing Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
Tue Oct 22 23:42:09 2019 Incoming Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
Tue Oct 22 23:42:09 2019 ROUTE_GATEWAY 192.168.1.1/255.255.255.0 IFACE=wlp3s0 HWADDR=ac:b5:7d:02:34:f3
Tue Oct 22 23:42:09 2019 TUN/TAP device tun0 opened
Tue Oct 22 23:42:09 2019 TUN/TAP TX queue length set to 100
Tue Oct 22 23:42:09 2019 do_ifconfig, tt->did_ifconfig_ipv6_setup=0
Tue Oct 22 23:42:09 2019 /sbin/ip link set dev tun0 up mtu 1500
Tue Oct 22 23:42:09 2019 /sbin/ip addr add dev tun0 local 10.20.0.10 peer 10.20.0.9
Tue Oct 22 23:42:09 2019 /sbin/ip route add 0.0.0.0/1 via 10.20.0.9
Tue Oct 22 23:42:09 2019 /sbin/ip route add 172.17.2.0/24 via 10.20.0.9
Tue Oct 22 23:42:09 2019 /sbin/ip route add 10.20.0.0/24 via 10.20.0.9
Tue Oct 22 23:42:09 2019 /sbin/ip route add 172.17.1.0/24 via 10.20.0.9
Error: Invalid prefix for given prefix length.
Tue Oct 22 23:42:09 2019 ERROR: Linux route add command failed: external program exited with error status: 2
Tue Oct 22 23:42:09 2019 /sbin/ip route add 10.20.0.1/32 via 10.20.0.9
Tue Oct 22 23:42:09 2019 Initialization Sequence Completed

Share script managed user VPN

Đây là đoạn script mình viết để đơn giản hóa việc tạo, xóa user VPN, bạn chạy script, lấy file tạo đựoc mang về máy local là quay đựoc VPN, mình gom tất cả lại thành 1 file duy nhất (nhớ tạo user PAM tuơng ứng nhé :D)

#!/bin/bash

options=("Create User" "Delete User" "Quit")

Create_user() {
   read -p "input username: " username
   echo "Creating user key for $username ..."
   useradd $username

   if [ ! -f /etc/openvpn/common-client.txt ]; then
    cat <<EOF >> /etc/openvpn/common-client.txt
client
dev tun
proto udp
remote 18.195.17.9 11194
resolv-retry 10
nobind
persist-key
persist-tun
verb 3

tun-mtu 1500
tun-mtu-extra 32
mssfix 1440
cipher AES-256-CBC

key-direction 1
remote-cert-tls server
tls-auth ta.key 1
auth-user-pass
auth-nocache
EOF
fi

   cd /etc/openvpn/easy-rsa/
    ./easyrsa gen-req $username nopass
    ./easyrsa sign-req client $username

    if [ ! -f ~/$username.ovpn ]; then
    	cat /etc/openvpn/common-client.txt > ~/$username.ovpn
        echo "<ca>" >> ~/$username.ovpn
        cat /etc/openvpn/easy-rsa/pki/ca.crt >> ~/$username.ovpn
        echo "</ca>" >> ~/$username.ovpn
        echo "<cert>" >> ~/$username.ovpn
        cat /etc/openvpn/easy-rsa/pki/issued/$username.crt >> ~/$username.ovpn
        echo "</cert>" >> ~/$username.ovpn
        echo "<key>" >> ~/$username.ovpn
        cat /etc/openvpn/easy-rsa/pki/private/$username.key >> ~/$username.ovpn
        echo "</key>" >> ~/$username.ovpn
        echo "<tls-auth>" >> ~/$username.ovpn
        cat /etc/openvpn/keys/ta.key >> ~/$username.ovpn
        echo "</tls-auth>" >> ~/$username.ovpn
        echo "Completed, please check ~/$username.ovpn"
    fi
}
Delete_user() {
   read -p "input username You want delete here: " username
   userdel $username
    cd /etc/openvpn/easy-rsa/
    ./easyrsa revoke $username
    ./easyrsa gen-crl
    rm -rf /etc/openvpn/easy-rsa/pki/reqs/$username.req
    rm -rf /etc/openvpn/easy-rsa/pki/issued/$username.crt
    rm -rf /etc/openvpn/easy-rsa/pki/private/$username.key
    echo "finished delete user"

}

PS3="Select options, Please: "
select opt in "${options[@]}"
do
    case $opt in
        "Create User")
        Create_user
        break
        ;;
        "Delete User")
        Delete_user
        break
        ;;
        "Quit")
        break
        ;;
        *) echo "invalid option"
    esac
done

Khi chạy script có dạng như sau:

[root@openvpn-sever ~]# ./manage-user-vpn.sh 
1) Create User
2) Delete User
3) Quit
Select options, Please:

Tổng kết

Đơn giản lắm, bạn cứ làm theo step của mình là sẽ thành công, mình có một trick để quay VPN mà không cần nhập user, password nữa, sẽ chia sẽ đến các bạn ở bài tuts sau. Cám ơn các bạn đã theo dõi bài viết hướng dẫn cài đặt OpenVPN trên CentOS 7 từ A-Z!