本教程將向您展示如何在與 HAProxy 相同的框中運行 OpenConnect VPN Server (ocserv) 和 Apache / Nginx。 OpenConnect (ocserv) 是 Cisco AnyConnect VPN 協議的開源實現。
先決條件
要遵循本教程,我們假設您已經使用 Let’s EncryptTLS 服務器證書設置了 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 在 CentOS8 / RHEL8 上設置 OpenConnect VPN 服務器 (ocserv)
確保 OpenConnect VPN 服務器和 Web 服務器同時使用端口 443
默認情況下,OpenConnect VPN 服務器偵聽端口 443。如果 Apache / Nginx 已經在監聽 443 端口,則 ocserv 將無法綁定 443 端口。可以將 ocserv 配置為偵聽不同的端口,但最終用戶必須在客戶端軟件中指定端口。如果用戶體驗很重要,則應避免這種情況。此外,由於更高的服務質量 (QoS) 優先級,TCP 端口 443 上的 TLS 流量通常更快。
通常,一個端口只能由一個進程使用。但是,您可以使用 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
這會導致 HAproxy 稍後偵聽公共 IP 地址,因此 ocserv 將偵聽 127.0.0.1。保存並關閉文件。然後重新啟動 ocserv。
sudo systemctl restart ocserv
其次,您還需要確保 Web 服務器只偵聽本地主機,而不是公共 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(Server Name Indication)功能來區分 VPN 流量和正常的 HTTPS 流量。
- 什麼時候
vpn.example.com
使用 TLS Client Hello,HAProxy 將流量重定向到 ocserv 後端。 - 什麼時候
www.example.com
使用 TLS Client Hello,HAProxy 將流量重定向到 apache / nginx 後端。 - 如果客戶端沒有使用 TLSClientHello 指定服務器名稱,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 應用程序不支持 TLSSNI,因此最好對其進行配置。 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
在 DNS 區域編輯器中,當您使用 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,請鏈接並將以下三行添加到此文件: 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 地址。 您可以通過 IPv4 VPN 隧道使用 IPv6。
包起來
我們希望本教程能幫助您在同一個盒子中運行 OpenConnect VPN 服務器和 Apache / Nginx。與往常一樣,如果您覺得這篇文章有用,請訂閱我們的免費時事通訊以獲取更多提示和技巧。照顧好自己?