Skip to main content

วิธีทำ VPN Server ที่บ้านสำหรับ Remote เข้าใช้งานได้ทุกที่ง่าย ๆ ด้วย Docker + OpenVPN

Kongvut Sangkla

Intro

สวัสดีครับ บทความนี้จะพาทำ VPN Server ด้วย Docker + OpenVPN แบบง่าย ๆ ไม่ถึง 10 นาทีเสร็จ สำหรับใช้เชื่อมต่อทรัพยากรต่าง ๆ ในบ้าน เมื่อเวลาเราอยู่นอกบ้านและมีความจำเป็นต้องใช้งานระบบต่าง ๆ ภายในบ้านของเราเอง เช่น

  • เข้าถึงไฟล์ต่าง ๆ ที่อยู่บ้าน
  • เข้าถึง Media server
  • เข้า Service ภายในต่าง ๆ ที่เรามี
  • เข้าถึง Computer เครื่องอื่น ๆ เป็นต้น

สิ่งที่ต้องมี

  • เครื่อง Server (เครื่องธรรมดา ๆ ก็ได้) ที่บ้านโดยจะเป็น OS อะไรก็ได้ ขอแค่มี Docker ติดตั้งไว้แล้วก็พอ (ในบทความใช้ OS: Ubuntu Server)
  • Public IP (หรือไม่ต้องมีก็ได้โดยแก้ปัญหาด้วยการทำ Port Forwarding ที่ Router แล้วไปใช้บริการ DDNS ของผู้ให้บริการอินเตอร์เน็ตที่เราใช้งานอยู่)

ขั้นตอน

ภาพรวมขั้นตอนทั้งหมดคือ

  1. เตรียมเครื่อง Server พร้อมติดตั้ง Docker ให้เรียบร้อย
  2. ติดตั้ง OpenVPN ด้วย Docker
  3. Port Forwarding ที่ Router ไปที่บริการ DDNS

1. เตรียมเครื่อง Server พร้อมติดตั้ง Docker ให้เรียบร้อย

เตรียมเครื่อง Server ที่จะใช้ทำเป็น VPN Server (เครื่องธรรมดา ๆ ก็ได้) ติดตั้ง OS และ Docker ให้เรียบร้อยในส่วนหัวข้อนี้จะไม่ลงรายละเอียดการติดตั้ง

2. ติดตั้ง OpenVPN ด้วย Docker

ขั้นตอนต่อไปนี้จะดำเนินการได้เมื่อ OS ต้องติดตั้ง Docker แล้วเท่านั้น

2.1 สร้าง Volume สำหรับเก็บ Configuration files และ Certificates files

คำสั่ง
cd
mkdir vpn-data

2.2 Pull OpenVPN docker image

คำสั่ง
docker run -v $PWD/vpn-data:/etc/openvpn \
--log-driver=none \
--rm kylemanna/openvpn ovpn_genconfig -u udp://SERVERNAME_OR_IP:PORT
อย่าลืมแก้ไขค่าตรงนี้

-u udp://SERVERNAME_OR_IP:PORT

ระบุ Domain name เช่น udp://vpn.example.com หรือใช้เลข IP ก็ได้ เช่น udp://10.0.0.1

ตัวอย่าง

-u udp://vpn.2my.xyz:54445

ระบุ Port ได้ตามที่ต้องการ (Default คือ 1194)

ผลลัพธ์
Unable to find image 'kylemanna/openvpn:latest' locally
latest: Pulling from kylemanna/openvpn
188c0c94c7c5: Pull complete
e470f824352c: Pull complete
d6ed0c7c142e: Pull complete
74586f3c5cd4: Pull complete
cb26244a2b2a: Pull complete
Digest: sha256:643531abb010a088f1e23a1c99d44f0bd417a3dbb483f809caf4396b5c9829a0
Status: Downloaded newer image for kylemanna/openvpn:latest
Processing PUSH Config: 'block-outside-dns'
Processing Route Config: '192.168.254.0/24'
Processing PUSH Config: 'dhcp-option DNS 8.8.8.8'
Processing PUSH Config: 'dhcp-option DNS 8.8.4.4'
Processing PUSH Config: 'comp-lzo no'
Successfully generated config
Cleaning up before Exit ...

2.3 การสร้างใบรับรอง CA certificate

คำสั่ง
docker run -v $PWD/vpn-data:/etc/openvpn \
--log-driver=none \
--rm -it kylemanna/openvpn ovpn_initpki
ผลลัพธ์
init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /etc/openvpn/pki


Using SSL: openssl OpenSSL 1.1.1g 21 Apr 2020

Enter New CA Key Passphrase:
Re-Enter New CA Key Passphrase:

ระบุ Key Passphrase (โปรดจดไว้ หรือจำให้ได้เพราะจำเป็นต้องใช้ในการสร้าง Client certificate)

ผลลัพธ์
Generating RSA private key, 2048 bit long modulus (2 primes)
...................................+++++
....+++++
e is 65537 (0x010001)
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) [Easy-RSA CA]:

ระบุชื่อ VPN Server ที่ต้องการ (แค่ชื่อเครื่องเฉย ๆ ระบุชื่ออะไรก็ได้)

ผลลัพธ์
CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/etc/openvpn/pki/ca.crt


Using SSL: openssl OpenSSL 1.1.1g 21 Apr 2020
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
...............................................................+......................+........................................................+...............................................................................................................................................................................................................................................................................................................................................................................+..........................+........................+............................................++*++*++*++*


DH parameters of size 2048 created at /etc/openvpn/pki/dh.pem

Using SSL: openssl OpenSSL 1.1.1g 21 Apr 2020
Generating a RSA private key
...............................................................................+++++
.......................................+++++
writing new private key to '/etc/openvpn/pki/easy-rsa-73.bipEoC/tmp.hBmGNb'
-----
Using configuration from /etc/openvpn/pki/easy-rsa-73.bipEoC/tmp.aENgfi
Enter pass phrase for /etc/openvpn/pki/private/ca.key:

ระบุ CA passphrase key (ที่จดไว้)

ผลลัพธ์
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'SERVERNAME_OR_IP'
Certificate is to be certified until Oct 18 10:55:06 2023 GMT (825 days)

Write out database with 1 new entries
Data Base Updated

Using SSL: openssl OpenSSL 1.1.1g 21 Apr 2020
Using configuration from /etc/openvpn/pki/easy-rsa-148.ApeBmK/tmp.MiHpkE
Enter pass phrase for /etc/openvpn/pki/private/ca.key:

An updated CRL has been created.
CRL file: /etc/openvpn/pki/crl.pem

ระบุ CA passphrase key อีกรอบ (ครั้งที่ 2)

note

CA certificate ที่สร้างมีอายุ 3 ปี (Oct 18 10:55:06 2023 GMT (825 days))

2.4 สั่ง Start service OpenVPN server

คำสั่ง
docker run -v $PWD/vpn-data:/etc/openvpn \
-d --name my-open-vpn \
-p 54445:54445/udp \
--cap-add=NET_ADMIN \
--restart unless-stopped \
kylemanna/openvpn

สามารถกำหนดชื่อ Container ได้ตามที่ต้องการตัวอย่าง --name my-open-vpn

ผลลัพธ์
308df2b2f8ad89cd2878c1e48....

2.5 การสร้างใบรับรอง client Certificate

คำสั่ง
docker run -v $PWD/vpn-data:/etc/openvpn \
--log-driver=none \
--rm -it kylemanna/openvpn easyrsa build-client-full ClientName nopass
อย่าลืมแก้ไขค่าตรงนี้

ClientName ระบุชื่อ Client ที่ต้องการ

ผลลัพธ์
Using SSL: openssl OpenSSL 1.1.1g  21 Apr 2020
Generating a RSA private key
.......+++++
......+++++
writing new private key to '/etc/openvpn/pki/easy-rsa-1.ejnOJD/tmp.gJOELh'
-----
Using configuration from /etc/openvpn/pki/easy-rsa-1.ejnOJD/tmp.LJKbAi
Enter pass phrase for /etc/openvpn/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:'ClientName'
Certificate is to be certified until Oct 18 10:41:08 2023 GMT (825 days)

Write out database with 1 new entries
Data Base Updated
note

Certificate ที่สร้างมีอายุ 3 ปี (Oct 18 10:41:08 2023 GMT (825 days))

2.6 ขอไฟล์ Client configuration

คำสั่ง
docker run -v $PWD/vpn-data:/etc/openvpn \
--log-driver=none \
--rm kylemanna/openvpn ovpn_getclient ClientName > ClientName.ovpn

ถึงขั้นตอนนี้ถ้าคุณลองสั่งคำสั่ง ls จะพบรายการเห็นไฟล์ ClientName.ovpn แสดงว่าคุณได้รับไฟล์ Client configuration เรียบร้อยแล้ว

3. Port Forwarding ที่ Router ไปที่บริการ DDNS

3.1 Port Forwarding ที่ Router

การ Port Forwarding ที่ Router นั้นให้ Forward UDP Port แต่ก็จะมีความแตกต่างกันไปตามแต่ละรุ่นของ Router โดยของผู้เขียนจะมีตัวอย่างดังนี้

Imgur

3.2 ทดลองเชื่อมต่อ

  1. คุณต้องทำการ Download ไฟล์ ClientName.ovpn มาเก็บไว้เครื่อง Client ที่ต้องการเชื่อมต่อ VPN (ในตัวอย่างนี้ผมจะใช้คำสั่ง scp สำหรับโอนไฟล์ลงมาเก็บไว้)
คำสั่ง
scp [email protected]:/home/bot4k/kongvut.ovpn ~/Documents/myVpnConfig
  1. คุณต้องติดตั้ง VPN Client App สำหรับการเชื่อมต่อ (จริง ๆ มีหลายตัวลองหาข้อมูลเพิ่มเติมได้) โดยตัวอย่างใช้ OpenVPN Connect for Mac Download ที่ https://openvpn.net/vpn-client/

img

  1. เมื่อติดตั้งเสร็จเปิด OpenVPN Connect จากนั้น Import ไฟล์ .opvn จากนั้นกดปุ่มเชื่อมต่อโดยหากไม่มีอะไรผิดพลาดจะมีผลลัพธ์ดังรูปภาพ
Figure Figure

สรุปขั้นตอนทั้งหมด

mkdir vpn-data

docker run -v $PWD/vpn-data:/etc/openvpn --log-driver=none --rm kylemanna/openvpn ovpn_genconfig -u udp://SERVERNAME_OR_IP:54445

docker run -v $PWD/vpn-data:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn ovpn_initpki

docker run -v $PWD/vpn-data:/etc/openvpn -d -p 54445:54445/udp --restart unless-stopped --cap-add=NET_ADMIN --name my-open-vpn kylemanna/openvpn

docker run -v $PWD/vpn-data:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn easyrsa build-client-full ClientName nopass

docker run -v $PWD/vpn-data:/etc/openvpn --log-driver=none --rm kylemanna/openvpn ovpn_getclient ClientName > ClientName.ovpn

สรุป

ถือว่าการทำ VPN Server ด้วย OpenVPN และ Docker นั้นง่ายมาก ๆ โดยส่วนตัวแล้วถือว่าชอบการติดตั้งนี้ เพราะความง่ายในการใช้งาน การจัดการ และวิธีที่การตั้งค่ามีความปลอดภัยค่อนข้างสูงทั้งบนฝั่งเซิร์ฟเวอร์และไคลเอนต์ ด้วยการใช้ CA certificate และ client certificate ในการเชื่อมต่อ

ถ้าวิธีนี้ยุ่งยากไปสามารถไปซื้อพวก Router ที่มีความสามารถทำตัวเองเป็น VPN Server ได้มาใช้แทนก็ได้ เช่น รุ่นนี้ รีวิว Router GL.iNet Opal (GL-SFT1200) Pocket-sized Travel รองรับการทำทั้งแบบ OpenVPN และ WireGuard

อัปเดทและขอแนะนำ

ผมเพิ่งพบว่า WireGuard นั้นเร็วแรงกว่า OpenVPN มาก และหลายบทความก็บอกเป็นเนื้อหาเดียวกันว่าเร็วกว่าจริง https://cybernews.com/what-is-vpn/wireguard-vs-openvpn/

Imgur

ตอนนี้ผมเปลี่ยนมาใช้ WireGuard แทน OpenVPN ได้สักพักแล้ว

การติดตั้ง WireGuard นั้นง่ายมาก ง่ายกว่า OpenVPN ด้วย โดยผมใช้ Docker Image ตัวนี้ https://hub.docker.com/r/linuxserver/wireguard ซึ่งเป็นได้ทั้ง Client mode และ Server Mode

เมื่อติดตั้งแล้ว Peer configs นั้นจะให้ไฟล์ .conf และ QR Code ซึ่ง .conf จะใช้ Import Tunnels ได้เลย (คล้าย ๆ ของ OpenVPN) ส่วน QR Code นั้นเอาไว้ใช้ Scan เพื่อเชื่อมต่อบน Mobile App ที่เป็น Client ของ WireGuard ได้เลยถือว่าสะดวกมาก

ปล. WireGuard App บน Mac รองรับ CPU ของ Apple Silicon ด้วยถือว่าดีมาก (ไม่เหมือนของ OpenVPN ยังเป็น Intel อยู่เลย 😅)

References

Loading...