本教程展示瞭如何在與 HAProxy 相同的機器上運行 OpenConnect VPN 服務器 (ocserv) 和 Apache/Nginx。 OpenConnect (ocserv) 是 Cisco AnyConnect VPN 協議的開源實現。
先決條件
遵循本教程假設您已經使用 Let’s Encrypt TLS 服務器證書設置了 OpenConnect VPN 服務器。如果沒有,請遵循以下教程之一。
- 使用 Let’s Encrypt 在 Ubuntu 20.04 上設置 OpenConnect VPN 服務器 (ocserv)
- 使用 Let’s Encrypt 在 Ubuntu 16.04/18.04 上設置 OpenConnect VPN 服務器 (ocserv)
- 使用 Let’s Encrypt 在 Debian 10 Buster 上設置 OpenConnect VPN 服務器 (ocserv)
- 使用 Let’s Encrypt 在 CentOS 8/RHEL 8 上設置 OpenConnect VPN 服務器 (ocserv)
讓 OpenConnect VPN 服務器和 Web 服務器同時使用端口 443
默認情況下,OpenConnect VPN 服務器偵聽端口 443。如果您已經讓 Apache/Nginx 監聽 443 端口,則 ocserv 將無法綁定 443 端口。儘管可以將 ocserv 配置為偵聽不同的端口,但它需要最終用戶在客戶端軟件中指定端口,如果用戶體驗受到關注,則應避免使用。此外,TCP 端口 443 上的 TLS 流量通常具有更高的 QoS(服務質量)優先級,速度更快。
一個端口通常只能由一個進程使用。但是,您可以通過 HAproxy(高可用性代理)和 SNI(服務器名稱指示)強制 ocserv 和 Apache/Nginx 使用端口 443。
觀察配置
首先,編輯 ocserv 配置文件。
sudo nano /etc/ocserv/ocserv.conf
取消註釋以下行。這允許 ocserv 獲取客戶端 IP 地址而不是 HAproxy IP 地址。
listen-proxy-proto = true
然後找到這一行:
#listen-host = [IP|HOSTNAME]
改成
listen-host = 127.0.0.1
這將導致 ocserv 監聽 127.0.0.1,因為 HAproxy 稍後將需要監聽公共 IP 地址。保存並關閉文件。然後重新啟動 ocserv。
sudo systemctl restart ocserv
其次,我們還需要確保我們的 Web 服務器只監聽 localhost,而不是我們的公共 IP 地址。
配置 Nginx
如果您使用的是 Nginx,請編輯服務器塊文件。
sudo nano /etc/nginx/conf.d/example.com.conf
在您的 SSL 服務器塊中,找到以下指令:
listen 443 ssl;
改成
listen 127.0.0.2:443 ssl;
這次讓我聽聽 127.0.0.2:443
因為 127.0.0.1:443
已經被 ocserv 佔用。保存並關閉文件。 Nginx 主配置文件 /etc/nginx/nginx.conf
和默認的服務器塊 /etc/nginx/sites-enabled/default
您可能還需要編輯此文件,因為可能有一個默認的虛擬主機在 443 上偵聽。
然後重啟 Nginx。
sudo systemctl restart nginx
阿帕奇配置
如果您使用 Apache Web 服務器,請編輯您的虛擬主機文件。
Debian/Ubuntu
sudo nano /etc/apache2/sites-enabled/example.com.conf
CentOS/RHEL
sudo nano /etc/httpd/conf.d/example.com.conf
在 SSL 虛擬主機中,更改
<VirtualHost *:443>
到達
<VirtualHost 127.0.0.2:443>
這次讓我聽聽 127.0.0.2:443
因為 127.0.0.1:443
已經被 ocserv 佔用。保存並關閉文件。
下一步編輯 /etc/apache2/ports.conf
Debian/Ubuntu 文件。
sudo nano /etc/apache2/ports.conf
編輯/etc/httpd/conf.d/ssl.conf
CentOS/RHEL 上的文件。
sudo nano /etc/httpd/conf.d/ssl.conf
改變
Listen 443
到達
Listen 127.0.0.2:443
保存並關閉文件。重啟阿帕奇。
sudo systemctl restart apache2
還
sudo systemctl restart httpd
HAProxy 配置
安裝 HAProxy。
sudo apt install haproxy
還
sudo dnf install haproxy
啟動 HAProxy
sudo systemctl start haproxy
編輯配置文件。
sudo nano /etc/haproxy/haproxy.cfg
如果您使用的是 Nginx,請將以下行複制並粘貼到文件末尾。交換 12.34.56.78
使用您的服務器的公共 IP 地址。交換 vpn.example.com
使用 ocserv 使用的域名, www.example.com
Web 服務器使用的域名。
frontend https bind 12.34.56.78:443 mode tcp tcp-request inspect-delay 5s tcp-request content accept if { req_ssl_hello_type 1 } use_backend ocserv if { req_ssl_sni -i vpn.example.com } use_backend nginx if { req_ssl_sni -i www.example.com } use_backend nginx if { req_ssl_sni -i example.com } default_backend ocserv backend ocserv mode tcp option ssl-hello-chk # pass requests to 127.0.0.1:443. Proxy protocol (v2) header is required by ocserv. server ocserv 127.0.0.1:443 send-proxy-v2 backend nginx mode tcp option ssl-hello-chk server nginx 127.0.0.2:443 check
如果您使用的是 Apache,請將以下行複制並粘貼到文件末尾。交換 12.34.56.78
使用您的服務器的公共 IP 地址。交換 vpn.example.com
使用 ocserv 使用的域名, www.example.com
Web 服務器使用的域名。
frontend https bind 12.34.56.78:443 mode tcp tcp-request inspect-delay 5s tcp-request content accept if { req_ssl_hello_type 1 } use_backend ocserv if { req_ssl_sni -i vpn.example.com } use_backend apache if { req_ssl_sni -i www.example.com } use_backend apache if { req_ssl_sni -i example.com } default_backend ocserv backend ocserv mode tcp option ssl-hello-chk # pass requests to 127.0.0.1:443. Proxy protocol (v2) header is required by ocserv. server ocserv 127.0.0.1:443 send-proxy-v2 backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 check
保存並關閉文件。然後重啟HAproxy。
sudo systemctl restart haproxy
在上面的配置中,我們利用 TLS 的 SNI(服務器名稱指示)功能來區分 VPN 流量和常規 HTTPS 流量。
- 什麼時候
vpn.example.com
對於 TLS Client Hello,HAProxy 將流量重定向到 ocserv 後端。 - 什麼時候
www.example.com
對於 TLS Client Hello,HAProxy 將流量重定向到 apache/nginx 後端。 - 如果客戶端沒有在 TLS Client Hello 中指定服務器名稱,HAproxy 將使用默認後端 (ocserv)。
你可以使用它 openssl
工具。首先,多次運行以下命令:
echo | openssl s_client -connect your-server-IP:443 | grep subject
由於我們沒有在上面的命令中指定服務器名稱,HAproxy 將始終將請求傳遞給默認後端(ocserv),並將其證書發送到客戶端。然後運行以下兩個命令:
echo | openssl s_client -servername www.example.com -connect your-server-IP:443 | grep subject echo | openssl s_client -servername vpn.example.com -connect your-server-IP:443 | grep subject
由於我們在命令中指定了服務器名稱,HAproxy 會根據我們定義的 SNI 規則傳遞請求。 Cisco AnyConnect 應用程序不支持 TLS SNI,我們建議對其進行配置。 ocserv
作為 HAProxy 配置文件中的默認後端。
如果您想更新網站的 Let’s Encrypt 證書, http-01
改為挑戰 tls-alpn-01
HAproxy 正在偵聽公共 IP 地址上的端口 443 並干擾更新過程。
sudo certbot renew --preferred-challenges http-01
修復了 HAProxy 中的一個錯誤
如果瀏覽器中沒有顯示 Apache/Nginx 網站,您將在 haproxy 日誌中看到以下消息 (/var/log/haproxy.log
)
Server nginx/nginx is DOWN, reason: Socket error, info: "Connection reset by peer backend nginx has no server available! Layer6 invalid response
後端 Nginx Web 服務器可能正在使用帶有 OCSP 必須裝訂擴展的 TLS 證書。 Nginx 不會在初始 HTTP 請求上發送 OCSP 裝訂信息。要使其正常工作,請將解析器添加到您的 Nginx 虛擬主機配置中,如下所示。
{
....
ssl_trusted_certificate /etc/letsencrypt/live/www.example.com/chain.pem;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
....
}
保存並關閉文件。然後重啟 Nginx。
sudo systemctl restart nginx
還可以考慮刪除 HAproxy 中的後端服務器運行狀況檢查。所以改變
server nginx 127.0.0.2:443 check
到達
server nginx 127.0.0.2:443
保存並關閉文件。然後重啟HAproxy。
sudo systemctl restart haproxy
如何使用 HAProxy 在 ocserv 上啟用 IPv6
一、創建AAAA記錄 vpn.example.com
因此,一旦您在 ocserv 中配置了 IPv6,您的 DNS 記錄就應該傳播到 Internet。
測試 IPv6 連接性
要使用 IPv6 協議建立 VPN 隧道,請確保您的 VPN 服務器具有公共 IPv6 地址。 (VPN 客戶端不需要有公共 IPv6 地址。)要檢查,請運行以下命令:
ip addr
找到您的主要網絡接口。如果你能找到它 inet6 .... scope global
使用如下行獲取公共 IPv6 地址:這個 inet6
地址在 scope link
私有 IPv6 地址。
然後轉到 https://test-ipv6.com/ 檢查您的 IPv6 連接。 如果您的 VPN 客戶端有一個公共 IPv6 地址,您就會知道您的 VPN 只保護一種協議,而不是同時保護兩種協議。這是因為我們沒有在 ocserv 中啟用 IPv6。
在 ocserv 中啟用 IPv6
要在 ocserv 中啟用 IPv6,請編輯 ocserv 配置文件。
sudo nano /etc/ocserv/ocserv.conf
查找並取消註釋以下兩行,以便您的 VPN 客戶端可以獲得私有 IPv6 地址。
ipv6-network = fda9:4efe:7e3b:03ea::/48 ipv6-subnet-prefix = 64
如果你看到這條線
ipv6-network = fda9:4efe:7e3b:03ea::/64
請將其更改為:
ipv6-network = fda9:4efe:7e3b:03ea::/48
保存並關閉文件。重新啟動 ocserv 以使更改生效。
sudo systemctl restart ocserv
為 IPv6 啟用 IP 轉發
接下來,您需要在 Linux 內核中為 IPv6 啟用 IP 轉發。編輯 sysctl.conf
文檔。
sudo nano /etc/sysctl.conf
將以下行添加到此文件的末尾:
net.ipv6.conf.all.forwarding=1
保存並關閉文件。然後使用以下命令應用更改:
sudo sysctl -p
在防火牆上設置 IPv6(Debian、Ubuntu)
接下來,我們需要在 UFW 防火牆上配置 IPv6 偽裝,使服務器成為 VPN 客戶端的虛擬路由器。
sudo nano /etc/ufw/before6.rules
默認情況下有一些規則。 filter
桌子。將以下行添加到此文件的末尾:交換 ens3
使用您自己的網絡接口名稱。 在 Nano 文本編輯器中, Ctrl+W
, 所以 Ctrl+V
.
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -o ens3 -j MASQUERADE
# End each table with the 'COMMIT' line or these rules won't be processed
COMMIT
默認情況下,UFW 禁用數據包轉發。您可以允許在私有 IPv6 網絡上轉發。查出 ufw6-before-forward
如果源 IP 或目標 IP 是 fda9:4efe:7e3b:03ea::/48
範圍。
# allow forwarding for VPN -A ufw6-before-forward -s fda9:4efe:7e3b:03ea::/48 -j ACCEPT -A ufw6-before-forward -d fda9:4efe:7e3b:03ea::/48 -j ACCEPT
保存並關閉文件。此外,防火牆的 INPUT 鏈必須允許 IPv6 VPN 客戶端。
sudo ufw allow in from fda9:4efe:7e3b:03ea::/48
重新啟動 UFW 以使更改生效。
sudo systemctl restart ufw
現在,如果我在 NAT 表中列出 POSTROUTING 鏈中的規則,我會得到:
sudo ip6tables -t nat -L POSTROUTING
您可以查看偽裝規則。
斷開當前 VPN 連接並添加 AAAA 記錄 vpn.example.com
重新建立您的 VPN 連接。然後轉到 https://test-ipv6.com/ 檢查您的 IPv6 連接。
在防火牆上設置 IPv6 (CentOS)
啟用 IPv6 偽裝。
sudo firewall-cmd --permanent --add-rich-rule="rule family="ipv6" source address="fda9:4efe:7e3b:03ea::/48" masquerade"
允許 INPUT 鏈中的 VPN 客戶端。
sudo firewall-cmd --permanent --add-rich-rule="rule family="ipv6" source address="fda9:4efe:7e3b:03ea::/48" accept"
重新加載 firewalld 以使更改生效。
sudo systemctl reload firewalld
在 BIND 解析器中配置 IPv6
在您的 VPN 服務器上運行您自己的 BIND DNS 解析器允許您: /etc/ocserv/ocserv.conf
使用文件將 VPN 服務器配置為 VPN 客戶端的 DNS 解析器。
dns = fda9:4efe:7e3b::1
保存並關閉文件。 要通過 IPv6 查詢 DNS 名稱,必須將 BIND 配置為允許 IPv6 VPN 客戶端。
Debian/Ubuntu
sudo nano /etc/bind/named.conf.options
查出 allow-recursion
更改參數如下:
allow-recursion { 127.0.0.1; 10.10.10.0/24; fda9:4efe:7e3b:03ea::/48; };
保存並關閉文件。 重新啟動 BIND9。
sudo systemctl restart bind9
中央操作系統
sudo nano /etc/named.conf
查出 allow-query
更改參數如下:
allow-query { 127.0.0.1; 10.10.10.0/24; fda9:4efe:7e3b:03ea::/48; };
保存並關閉文件。 重新啟動 BIND9。
sudo systemctl restart named
使用 HAProxy 設置 IPv6
編輯 HAProxy 配置文件。
sudo nano /etc/haproxy/haproxy.cfg
製作 https
前端偵聽 IPv4 和 IPv6 地址。顯然,您應該使用自己服務器的公共 IPv6 地址。
frontend https bind 12.34.56.78:443 bind 2607:f8b0:4006:810::200e:443 mode tcp tcp-request inspect-delay 5s tcp-request content accept if { req_ssl_hello_type 1 }
然後找到 ocserv
將其添加到您的後端並添加 IPv6 服務器。
backend ocserv mode tcp option ssl-hello-chk server ocserv 127.0.0.1:443 send-proxy-v2 server ocserv6 [::1]:443 send-proxy-v2
保存並關閉文件。
讓 ocserv 兩個都聽 127.0.0.1
什麼時候 ::1
,編輯 /etc/hosts
文檔。
sudo nano /etc/hosts
編輯條目 127.0.0.1
什麼時候 ::1
如下, vpn.example.com
一個主機名可以解析為兩個地址。
127.0.0.1 localhost vpn.example.com ::1 ip6-localhost ip6-loopback vpn.example.com
保存並關閉文件。然後編輯 ocserv 配置文件。
sudo nano /etc/ocserv/ocserv.conf
找到這一行:
listen-host = 127.0.0.1
改成
listen-host = vpn.example.com
ocserv 檢測 IPv4 和 IPv6 地址 vpn.example.com
裡面 /etc/hosts
文件和綁定 127.0.0.1
什麼時候 ::1
地址。保存並關閉文件。然後重啟 ocserv 和 HAProxy。
sudo systemctl restart ocserv sudo systemctl restart haproxy
通過運行以下命令檢查 ocserv 的偵聽狀態:你會看到它同時在聽 127.0.0.1
什麼時候 ::1
.
sudo ss -lnpt | grep ocserv
測試 IPv6 連接性
重新啟動您的 VPN 客戶端並訪問 https://test-ipv6.com/ 以檢查 IPv6 連接。如果一切順利,您應該會在測試結果中看到您的 VPN 服務器的 IPv4 和 IPv6 地址。並且“VPN 僅保護一種協議”警告應該消失。
如果測試結果沒有顯示 VPN 服務器的 IPv6 地址,您可能需要重新啟動 VPN 客戶端以重新建立 VPN 連接。
筆記: VPN 客戶端不需要公共 IPv6 地址。 您可以使用 IPv6 over IPv4 VPN 隧道。
包起來
我希望本教程可以幫助您在同一個機器上運行 OpenConnect VPN 服務器和 Apache/Nginx。與往常一樣,如果您發現這篇文章有幫助,請註冊我們的免費新聞通訊以獲取提示和技巧。照顧好自己?