十分鐘 OpenVPN server 架設 - docker 手把手教學

本篇分享如何透過 docker 自行架設 OpenVPN server,若架設在便宜的雲端服務,還可以節省一大筆 VPN 的費用!立刻來看看如何架設!

Build OpenVPN Image

我們使用 kylemanna/docker-openvpn 來實作,因為 dockerhub 上只有 x86 image,如果是 arm 平台則需要自己 build(x86 可跳過)

clone repo 後,直接 build

$ git clone https://github.com/kylemanna/docker-openvpn
$ cd docker-openvpn
$ docker build -t kylemanna/openvpn -f Dockerfile.aarch64 .

如果發生找不到 aarch64/alpine:3.5 的錯誤,修改 Dockerfile 中的 base image 為

FROM alpine:3.15.4

或更新的 alpine 版本即可

建立 Server Config 以及 Certificate

Step 1:建立 Config 資料夾

在 host 新增一資料夾 data,作為存放 OpenVPN config 和 certificate 的地方

mkdir data

Step 2:初始化基本的 Configuration

我們透過 docker run --rm 指令起一次性的 container,掛入 host data folder,執行 ovpn_genconfig 指令,並帶入 host 的 ip 或者 domain

docker run -v $PWD/data:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://<your host ip or domain>

step 3:初始化 Server 的 Certificate

一樣的方法,跑一下 ovpn_initpki 指令,但需要加 -it,因為建立 certificate 過程中會需要設定密碼

docker run -v $PWD/data:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki

啟動 OpenVPN container

使用以下 docker-compose 檔案起 OpenVPN container 作為 VPN service

其中幾個參數比較重要:
1. 一定要加 cap_add: - NET_ADMIN
2. 一定要 open 1194 port,udp 即可
3. 一定要 mount data folder/etc/openvpn,才能確保 container 讀取到一開始做的設定
4. 其他參數可以依需求自由調整

version: '2.3'
services:
  openvpn-service:
    image: kylemanna/openvpn 
    container_name: openvpn-service
    cap_add: 
      - NET_ADMIN
    restart: always
    mem_limit: 64M
    logging:
      driver: "json-file"
      options:
        max-size: "1m"
        max-file: "3"
    ports:
      - "1194:1194/udp"
    networks:
      - openvpn-service
    volumes:
      - ./data:/etc/openvpn

networks:
  openvpn-service:
    name: openvpn-service-network
    driver: bridge

別忘記啟動他

docker-compose up -d

產生 Client Certificate

Step 1:產生 Client Certificate

接下來產生對應的無密碼 client certificate,其中 client name 可隨意替換成自己想要的。過程中會詢問一開始建立的 server certificate 密碼,可不要忘記了XD

docker run -v $PWD/data:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full [client name] nopass

Step 2:將 Client Certificate 匯出成 ovpn file

將剛剛產生的 client certificate 匯出成 ovpn file,以利後續 App 直接讀入完成設定

docker run -v $PWD/data:/etc/openvpn --rm kylemanna/openvpn ovpn_getclient [client name] > [client name].ovpn

用 OpenVPN Connect App 測試連線

把剛剛匯出的 ovpn 檔案放到手機,打開 OpenVPN Connect App,點選 Import Profile,切換到 file tab,點剛剛的 ovpn file

十分鐘 OpenVPN server 架設 - docker 手把手教學

自動完成所有設定!立刻就能連線測試看看!

十分鐘 OpenVPN server 架設 - docker 手把手教學

同 Certificate 多重連線問題

實測發現,一個 client certificate 同一時間僅能一個 device 使用。如果第二台使用相同的 client certificate 連線,第一台會被中斷。

在 OpenVPN log 中也會看到錯誤訊息:

2022-04-16 05:53:38 MULTI: new connection by client 'j' will cause previous active sessions by this client to be dropped.  Remember to use the --duplicate-cn option if you want multiple clients using the same certificate or username to concurrently connect.

log 中建議如果要啟用多重連線的話,需要加 --duplicate-cn 參數。但在這篇討論中不建議加,原因是:

  1. 如果多人共用同一個 client certificate,一但 certificate 被廢除,會影響多位使用者
  2. 如果要提供裝置漫遊,則不能開啟多連線功能。因為當一個裝置更換 IP 重新建立 VPN 時,應該要回收掉前一個連線,若限制連線數即可達成此需求。

若手上有多個裝置需要同時連線,最快解法就是多產生幾個 client certificate 來使用,反正不用錢,愛產幾個就幾個XD

範例原始碼在此下載:github

延伸閱讀:
十分鐘架設自己的 VPN server

Written by J
雖然大學唸的是生物,但持著興趣與熱情自學,畢業後轉戰硬體工程師,與宅宅工程師們一起過著沒日沒夜的生活,做著台灣最薄的 intel 筆電,要與 macbook air 比拼。 離開後,憑著一股傻勁與朋友創業,再度轉戰軟體工程師,一手扛起前後端、雙平台 app 開發,過程中雖跌跌撞撞,卻也累計不少經驗。 可惜不是那 1% 的成功人士,於是加入其他成功人士的新創公司,專職開發後端。沒想到卻在採前人坑的過程中,拓寬了眼界,得到了深層的領悟。