Routing traffic of Docker containers through a VPN container.
Gluetun,一款專為Docker設計的開源軟體,可讓特定容器走VPN連線上網。
容器為什麼沒事要連VPN?嗯,Ivon覺得下載BT就是個好理由。
試想:如果我們將下載BT種子的qBittorrent服務跑在Docker裡面,並透過專門的VPN連線,就可以達成跟主機分開上網的功效。也就是說,Linux電腦看網頁時仍透過正常網路上網,電腦不會全域都是走VPN連線,唯有容器部份的服務走VPN。如此一來透過VPN做種就不會干擾正常電腦使用了。
現在讓我們繼續談Gluetun,名字音近麩質,但其實應該是強力膠水的意思,或許可以解釋為「把TUN(虛擬網路裝置)黏在一起」。
開發者Quentin McGaw在 Github放的圖示是二個水管,好像在玩瑪莉歐,這裡進去那裡出來。
Gluetun本身是作為VPN客戶端兼代理伺服器,支援連線至許多商業VPN,所有您聽過名字的大牌VPN都支援。商業VPN多半支援OpenVPN或WireGuard協定,只要到他們網站下載帶有密鑰的設定檔,Gluetun就能夠連上該公司的VPN。
為防止洩漏IP,Gluetun還會在VPN連線有問題的時候啟動Kill Switch,自動斷線,使依賴它的容器跟著無法上網。
1. 取得VPN供應商的設定檔#
這裡Ivon使用ProtonVPN做示範,其他家VPN的設定大同小異,各大商業VPN應該都會有地方可以下載OpenVPN或WireGuard的設定檔。
OpenVPN#
請參閱 ProtonVPN官方文件,到你的 Proton VPN帳號後台,取得OpenVPN帳號密碼。
WireGuard#
請參閱 ProtonVPN官方文件,進入Downloads頁面,下滑到WireGuard,填寫服務名稱
在下方列表選取負載低的伺服器,由於我是付費方案所以有更多伺服器可選。點選Create。
下載WireGuard設定檔
2. 架設Gluetun服務#
由於等一下我們要讓容器走Gluetun的VPN,需要做些特別設定,編輯完後先別急著啟動Gluetun服務。
- 參考 Gluetun文件,新增docker-compose
cd ~
mkdir gluetun
cd gluetun
vim docker-compose.yml
- 參考剛才取得的VPN設定檔內容,依序填入
environment
的參數。如果有需要也可以給容器設定固定IP。
OpenVPN#
填入OpenVPN的帳號、密碼,並指定伺服器國家
version: "3"
services:
gluetun:
image: qmcgaw/gluetun
container_name: gluetun
restart: unless-stopped
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
ports:
- 8888:8888/tcp # HTTP proxy
- 8388:8388/tcp # Shadowsocks
- 8388:8388/udp # Shadowsocks
volumes:
- /home/user/gluetun:/gluetun
environment: # 按照VPN供應商的OpenVPN設定檔填寫
- VPN_SERVICE_PROVIDER=protonvpn
- VPN_TYPE=openvpn
- OPENVPN_USER=
- OPENVPN_PASSWORD=
- SERVER_COUNTRIES=United Kingdom # 指定國家
networks: # (選擇性) 固定Gluetun容器的IP
network:
ipv4_address: 172.27.0.5
networks: # (選擇性) 固定Gluetun容器的IP
network:
driver: bridge
ipam:
config:
- subnet: 172.27.0.0/16
gateway: 172.27.0.5
WireGuard#
按照VPN供應商的WireGuard設定檔填寫。
version: "3"
services:
gluetun:
image: qmcgaw/gluetun
container_name: gluetun
restart: unless-stopped
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
ports:
- 8888:8888/tcp # HTTP proxy
- 8388:8388/tcp # Shadowsocks
- 8388:8388/udp # Shadowsocks
volumes:
- /home/user/gluetun:/gluetun
environment:
- VPN_SERVICE_PROVIDER=custom
- VPN_TYPE=wireguard
- VPN_ENDPOINT_IP=
- VPN_ENDPOINT_PORT=
- WIREGUARD_PUBLIC_KEY=
- WIREGUARD_PRIVATE_KEY=
- WIREGUARD_ADDRESSES= #只要填IPV4位址就好
networks: # (選擇性) 固定Gluetun容器的IP
network:
ipv4_address: 172.27.0.5
networks: # (選擇性) 固定Gluetun容器的IP
network:
driver: bridge
ipam:
config:
- subnet: 172.27.0.0/16
gateway: 172.27.0.5
3. 讓容器走Gluetun的VPN連線#
- 相關文章: qBittorrent操作教學
欲使容器走Gluetun的VPN連線,只需讓其使用該網路上網即可。
如果容器服務跟Gluetun寫在同一個docker-compose:加入網路模式network_mode: "service:gluetun"
如果該容器跟Gluetun不是寫在同一個docker-compose:加入network_mode: "container:gluetun"
- 由於我的qBittorrent服務跟Gluetun不在同一個docker-compose,為此修改qBittorrent的docker-compose。下面是我位於
~/qbittorrent
目錄的檔案內容:
version: '3'
services:
qbittorrent:
image: lscr.io/linuxserver/qbittorrent:latest
container_name: qbittorrent
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Taipei
- WEBUI_PORT=8080
volumes:
- /home/user/qbittorrent/config:/config
- /home/user/qbittorrent/downloads:/downloads
ports:
- 8080:8080
- 6881:6881
- 6881:6881/udp
restart: unless-stopped
- 首先把qBittorrent暴露的通訊埠註解掉,因為這個會跟Gluetun網路衝突
#ports:
#- 8080:8080
#- 6881:6881
#- 6881:6881/udp
- 接著,在最下方加入Gluetun網路
network_mode: "container:gluetun"
- 現在還要處理qBittorrent通訊埠的問題。開啟Gluetun的docker-compose檔案,把qBittorrent用到的8080通訊埠加回來:
version: "3"
services:
gluetun:
image: qmcgaw/gluetun
container_name: gluetun
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
ports:
- 8888:8888/tcp # HTTP proxy
- 8388:8388/tcp # Shadowsocks
- 8388:8388/udp # Shadowsocks
- 8080:8080 # qBittorrent,左邊的可以自由改成想暴露的通訊埠,右邊則必須是容器本身的通訊埠
- 之後,依序啟動Gluetun和qBittorrent的服務
cd ~/gluetun
docker compose up -d
cd ~/qbittorrent
docker compose up -d
- 檢查容器有無連上VPN,用docker exec進入qBittorrent容器的shell:
docker ps
docker exec -ti qbittorrent /bin/bash
- 檢查公共IP
curl ifconfig.io
容器公共IP應當跟您選擇的VPN伺服器一致:
如果你想測試Kill Switch有無運作,停掉Gluetun服務,再檢查qBittorrent能不能上網就知道了:
cd ~/gluetun
docker compose down
docker exec -ti qbittorrent /bin/bash
curl ifconfig.io
4. 設定通訊埠轉發#
此為選擇性功能。
如果你要提昇BT下載速度,並讓別人從你這裡下載檔案(做種),最好設定通訊埠轉發(port forwarding)。
注意不是每一家VPN供應商都有提供此功能。且就算VPN供應商有提供通訊埠轉發,也不是每台伺服器都有此功能。
Gluetun支援Proton VPN和Private Internet Access,其他家的VPN請參閱官方網站的文件。
鑑於Gluetun取得轉發通訊埠的方法有缺失,似乎只能用OpenVPN方式連線,用WireGuard的話會找不到VPN供應商所轉發的通訊埠。
參考 Proton VPN官方文件,查看哪些國家伺服器支援P2P。
參考 Gluetun有關port forwarding的說明,按照Proton VPN提供的OpenVPN帳號,修改Gluetun的
docker-compose.yml
,在你的帳號名稱後面加上+pmp
加入以下環境變數:
environment:
- VPN_PORT_FORWARDING=on
- VPN_PORT_FORWARDING_PROVIDER=protonvpn
- 加入這段,啟用的Gluetun的Conrol Server
ports:
- 8000:8000
- 重新啟動Gluetun服務。
cd ~/gluetun
docker compose down
docker compose up -d
- Proton VPN所轉發的通訊埠可從此網址得知。(Gluetun的docker log也會寫出來)
curl http://Gluetun容器IP:8000/v1/openvpn/portforwarded
在qBittorrent偏好設定 → 連線開啟通訊埠,填入Proton VPN所轉發的通訊埠,並關閉UPnP功能。
要知道通訊埠轉發有無成功,進入Gluetun容器,使用port-checker程式檢測。這裡假定轉發的通訊埠為61915
docker ps
docker exec -it gluetun /bin/sh
wget -qO port-checker https://github.com/qdm12/port-checker/releases/download/v0.3.0/port-checker_0.3.0_linux_amd64
chmod +x port-checker
./port-checker -port 61915
- 開啟瀏覽器,輸入
http://VPN的公共IP:61915
,應該就會印出你目前的IP位址了。回到終端機,按CTRL+C關閉,並輸入exit退出shell。
5. 存取連上VPN的容器服務#
以qBittorrent來說,連上Gluetun的VPN後,該容器就只能從http://localhost:8080
存取,打http://伺服器IP:8080
是無效的。
所幸,剛才我們已經將qBittorrent的8080通訊埠加到Gluetun的docker-compose,您應當可以打http://伺服器IP:8080
或http://Gluetun的容器IP:8080
存取qBittorrent的網頁界面!
(Gluetun容器的IP可以用docker inspect "gluetun" | grep "IPAddress"
取得)
實測在使用 內網穿透軟體的情況下依然可以存取qBittorrent。
如果同一網路下的其他容器服務要連線至qBittorrent的容器,那麼就是打http://伺服器IP:8080
或http://Gluetun的容器IP:8080
來連線。
不過BT管理軟體
Sonarr比較特別,其docker-compose相關的容器也必須使用network_mode: "container:gluetun"
才可以連線到qBittorrent。
當Gluetun偵測VPN無法連線後會讓網路斷線,您需要重新啟動Gluetun服務,以及使用Gluetun網路的容器。
參考資料#
下面這篇文章有討論Gluetun反向代理與自動重啟容器服務的進階設定,但該名作者竟然一次幫兩家商業VPN打廣告😅
Gluetun Docker Guide – Easy VPN Killswitch for Docker Containers - SmartHomeBeginner