# 部署ocserv VPN服务器

Cisco AnyConnect是非常流行的SSL VPN客户端，并且跨平台，常见于iOS，Android，BlackBerry平台。由于我同时使用Linux，Mac，iPhone，黑莓，所以为了方便使用，采用通用的[OpenConnect VPN Server - ocserv](https://github.com/huataihuang/cloud-atlas-draft/tree/6f3204fffc11cf006abd394631e2598d98b415c3/security/vpn/openconnect/www.infradead.org/ocserv/README.md)（兼容Cisco AnyConnect的开源解决方案）来部署VPN Server。

* 源代码下载

从 [ocserv gitlab软件库](https://gitlab.com/groups/ocserv) 下载最新源代码

```bash
git clone https://gitlab.com/ocserv/ocserv.git
```

* 编译依赖

Debian和Fedora编译依赖软件库分别是 `libgnutls28-dev` 和 `gnutls-devel` ，此外，对应的一些可选功能依赖库如下

```bash
TCP wrappers: libwrap0-dev       / tcp_wrappers-devel
PAM:          libpam0g-dev       / pam-devel
LZ4:          liblz4-dev         / lz4-devel
seccomp:      libseccomp-dev     / libseccomp-devel
occtl:        libreadline-dev    / readline-devel
              libnl-route-3-dev  / libnl3-devel
GSSAPI:       libkrb5-dev        / krb5-devel
```

开发依赖库如下

```bash
libprotobuf-c0-dev / protobuf-c-devel
libtalloc-dev      / libtalloc-devel
libhttp-parser-dev / http-parser-devel
libpcl1-dev        / pcllib-devel
libopts25-dev      / autogen-libopts-devel
autogen            / autogen
protobuf-c-compiler/ protobuf-c
gperf              / gperf
```

Debian/Ubuntu按照以下命令准备依赖库安装 （参考 [Setup OpenConnect VPN Server for Cisco AnyConnect on Ubuntu 14.04 x64](https://www.vultr.com/docs/setup-openconnect-vpn-server-for-cisco-anyconnect-on-ubuntu-14-04-x64)）

```bash
apt-get install build-essential pkg-config libgnutls28-dev libwrap0-dev libpam0g-dev libseccomp-dev libreadline-dev libnl-route-3-dev
```

> 上述依赖包安装缺少 `lbopts25-dev` ，编译时候发现报错，所以补充安装了官方文档中说明的所有可选依赖开发库

* 编译 ocserv

如果是发行版本

```bash
./configure && make
```

如果是git版本

```bash
autoreconf -fvi
./configure && make
```

报错

```bash
make[3]: Entering directory '/root/ocserv/libopts'
  CC       libopts_a-libopts.o
In file included from libopts.c:24:0:
enum.c: In function ‘enum_err’:
enum.c:112:13: warning: embedded ‘\0’ in format [-Wformat-contains-nul]
             fprintf(option_usage_fp, ENUM_ERR_LINE, *(paz_names++));
             ^
enum.c:135:9: warning: embedded ‘\0’ in format [-Wformat-contains-nul]
         sprintf(zFmt, ENUM_ERR_WIDTH, (int)max_len);
         ^
```

尝试改成

```bash
./configure --enable-local-libopts
```

报错改成

```bash
make[2]: Entering directory '/root/ocserv/src'
: ocpasswd-args.def
: ocserv-args.def
protoc-c --c_out=. --proto_path=. ipc.proto
/bin/bash: protoc-c: command not found
Makefile:1779: recipe for target 'ipc.pb-c.c' failed
```

解决方法参考 [OpenConnect on Ubuntu](https://sskaje.me/2014/02/openconnect-ubuntu/) 并按照官方文档安装所有可选依赖开发库DTLS Dead Peer Detection detected dead peer!

```bash
apt-get install libprotobuf-c0-dev libtalloc-dev libhttp-parser-dev libpcl1-dev libopts25-dev autogen protobuf-c-compiler gperf
```

然后重新编译就可以通过

```bash
./configure
make
```

安装

```bash
make install
```

## 配置ocserv

首先需要创建自己的CA证书和服务器证书

```bash
cd ~
apt-get install gnutls-bin
mkdir certificates
cd certificates
```

创建CA模版文件 `ca.tmpl` ，这里`cn`请设置成自己组织的cn

```bash
cn = "VPN CA" 
organization = "Big Corp" 
serial = 1 
expiration_days = 3650
ca 
signing_key 
cert_signing_key 
crl_signing_key
```

生成CA密钥和CA证书

```bash
certtool --generate-privkey --outfile ca-key.pem
certtool --generate-self-signed --load-privkey ca-key.pem --template ca.tmpl --outfile ca-cert.pem
```

然后使用以下内容创建本地服务器证书模版文件（`server.tmpl`），注意`cn`字段，必须符合你服务器的DNS名字或者IP地址

```bash
cn = "you domain name or ip"
organization = "MyCompany" 
expiration_days = 3650 
signing_key 
encryption_key
tls_www_server
```

然后创建服务器密钥和证书

```bash
certtool --generate-privkey --outfile server-key.pem
certtool --generate-certificate --load-privkey server-key.pem --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem --template server.tmpl --outfile server-cert.pem
```

复制密钥、证书和配置文件到ocserv配置目录

```bash
mkdir /etc/ocserv
cp server-cert.pem server-key.pem /etc/ocserv
cd ~/ocserv/doc
cp sample.config /etc/ocserv/config
cd /etc/ocserv
```

编辑 `/etc/ocserv/config` 配置文件，类似如下

```bash
auth = "plain[/etc/ocserv/ocpasswd]"

try-mtu-discovery = true

server-cert = /etc/ocserv/server-cert.pem
server-key = /etc/ocserv/server-key.pem

tcp-port = 9000
udp-port = 9001
dns = 8.8.8.8

# comment out all route fields
#route = 10.10.10.0/255.255.255.0
#route = 192.168.0.0/255.255.0.0
#route = fef4:db8:1000:1001::/64
#no-route = 192.168.5.0/255.255.255.0
cisco-client-compat = true
```

> `no-route`配置可能需要根据自己的局域网配置调整。此外，对于国内网段，设置no-route可以避免国内流量通过vpn降低访问效率。
>
> 默认端口是`443`，这里改成`9000`

另外，参考 [安装配置AnyConnect服务端软件-ocserv](http://www.lichanglin.cn/%E5%AE%89%E8%A3%85%E9%85%8D%E7%BD%AEAnyConnect%E6%9C%8D%E5%8A%A1%E7%AB%AF%E8%BD%AF%E4%BB%B6-ocserv/)做一些配置优化调整

```bash
#同一个用户最多同时登陆数
max-same-clients = 10
# Dead peer detection in seconds.
dpd = 900
# Dead peer detection for mobile clients. The needs to
# be much higher to prevent such clients being awaken too
# often by the DPD messages, and save battery.
# (clients that send the X-AnyConnect-Identifier-DeviceType)
mobile-dpd = 1800

output-buffer = 23000 
try-mtu-discovery = true 

# The time (in seconds) that a client is allowed to stay idle (no traffic)
# before being disconnected. Unset to disable.
idle-timeout = 3600

# The time (in seconds) that a mobile client is allowed to stay idle (no
# traffic) before being disconnected. Unset to disable.
mobile-idle-timeout = 3600
```

创建用户登录帐号

```bash
ocpasswd -c /etc/ocserv/ocpasswd username
```

激活NAT

```bash
iptables -t nat -A POSTROUTING -j MASQUERADE
```

激活IPv4 forwarding，编辑`/etc/sysctl.conf`

```bash
net.ipv4.ip_forward=1
```

并使之生效

```bash
sysctl -p /etc/sysctl.conf
```

启动ocserv

```bash
ocserv -c /etc/ocserv/config
```

> 注意：Cisco AnyConnect客户端配置要同时写上服务器IP地址和端口，类似 `IP:PORT`

Debug方法

```bash
ocserv -c /etc/ocserv/config -d 9 -f
```

> `-d` 参数设置debug级别，从`0-999`

## 路由设置

参考 [Oc­serv 在 De­bian 下的安装与配置指南](https://darknode.in/network/setup-debian-ocserv/)，在 `/etc/ocserv/config` 中添加配置

```bash
no-route = 0.0.0.0/255.0.0.0
no-route = 1.0.0.0/255.128.0.0
no-route = 1.160.0.0/255.224.0.0
no-route = 1.192.0.0/255.224.0.0
no-route = 10.0.0.0/255.0.0.0
no-route = 14.0.0.0/255.224.0.0
no-route = 14.96.0.0/255.224.0.0
no-route = 14.128.0.0/255.224.0.0
no-route = 14.192.0.0/255.224.0.0
no-route = 27.0.0.0/255.192.0.0
no-route = 27.96.0.0/255.224.0.0
no-route = 27.128.0.0/255.128.0.0
no-route = 36.0.0.0/255.192.0.0
no-route = 36.96.0.0/255.224.0.0
no-route = 36.128.0.0/255.128.0.0
no-route = 39.0.0.0/255.224.0.0
no-route = 39.64.0.0/255.192.0.0
no-route = 39.128.0.0/255.192.0.0
no-route = 42.0.0.0/255.0.0.0
no-route = 43.224.0.0/255.224.0.0
no-route = 45.64.0.0/255.192.0.0
no-route = 47.64.0.0/255.192.0.0
no-route = 49.0.0.0/255.128.0.0
no-route = 49.128.0.0/255.224.0.0
no-route = 49.192.0.0/255.192.0.0
no-route = 54.192.0.0/255.224.0.0
no-route = 58.0.0.0/255.128.0.0                                          
no-route = 58.128.0.0/255.224.0.0                                        
no-route = 58.192.0.0/255.192.0.0                                        
no-route = 59.32.0.0/255.224.0.0                                         
no-route = 59.64.0.0/255.192.0.0                                         
no-route = 59.128.0.0/255.128.0.0                                        
no-route = 60.0.0.0/255.192.0.0                                          
no-route = 60.160.0.0/255.224.0.0                                        
no-route = 60.192.0.0/255.192.0.0                                        
no-route = 61.0.0.0/255.192.0.0                                          
no-route = 61.64.0.0/255.224.0.0                                         
no-route = 61.128.0.0/255.192.0.0                                        
no-route = 61.224.0.0/255.224.0.0
no-route = 100.64.0.0/255.192.0.0
no-route = 101.0.0.0/255.128.0.0
no-route = 101.128.0.0/255.224.0.0
no-route = 101.192.0.0/255.192.0.0
no-route = 103.0.0.0/255.192.0.0
no-route = 103.224.0.0/255.224.0.0
no-route = 106.0.0.0/255.128.0.0
no-route = 106.224.0.0/255.224.0.0
no-route = 110.0.0.0/254.0.0.0
no-route = 112.0.0.0/255.128.0.0
no-route = 112.128.0.0/255.224.0.0
no-route = 112.192.0.0/255.192.0.0
no-route = 113.0.0.0/255.128.0.0
no-route = 113.128.0.0/255.224.0.0
no-route = 113.192.0.0/255.192.0.0
no-route = 114.0.0.0/255.128.0.0
no-route = 114.128.0.0/255.224.0.0
no-route = 114.192.0.0/255.192.0.0
no-route = 115.0.0.0/255.0.0.0
no-route = 116.0.0.0/255.0.0.0
no-route = 117.0.0.0/255.128.0.0
no-route = 117.128.0.0/255.192.0.0
no-route = 118.0.0.0/255.224.0.0
no-route = 118.64.0.0/255.192.0.0
no-route = 118.128.0.0/255.128.0.0
no-route = 119.0.0.0/255.128.0.0
no-route = 119.128.0.0/255.192.0.0
no-route = 119.224.0.0/255.224.0.0
no-route = 120.0.0.0/255.192.0.0
no-route = 120.64.0.0/255.224.0.0
no-route = 120.128.0.0/255.224.0.0
no-route = 120.192.0.0/255.192.0.0
no-route = 121.0.0.0/255.128.0.0
no-route = 121.192.0.0/255.192.0.0
no-route = 122.0.0.0/254.0.0.0
no-route = 124.0.0.0/255.0.0.0
no-route = 125.0.0.0/255.128.0.0
no-route = 125.160.0.0/255.224.0.0
no-route = 125.192.0.0/255.192.0.0
no-route = 127.0.0.0/255.0.0.0
no-route = 139.0.0.0/255.224.0.0
no-route = 139.128.0.0/255.128.0.0
no-route = 140.64.0.0/255.224.0.0
no-route = 140.128.0.0/255.224.0.0
no-route = 140.192.0.0/255.192.0.0
no-route = 144.0.0.0/255.192.0.0
no-route = 144.96.0.0/255.224.0.0
no-route = 144.224.0.0/255.224.0.0
no-route = 150.0.0.0/255.224.0.0
no-route = 150.96.0.0/255.224.0.0
no-route = 150.128.0.0/255.224.0.0
no-route = 150.192.0.0/255.192.0.0
no-route = 152.96.0.0/255.224.0.0
no-route = 153.0.0.0/255.192.0.0
no-route = 153.96.0.0/255.224.0.0
no-route = 157.0.0.0/255.192.0.0
no-route = 157.96.0.0/255.224.0.0
no-route = 157.128.0.0/255.224.0.0
no-route = 157.224.0.0/255.224.0.0
no-route = 159.224.0.0/255.224.0.0
no-route = 161.192.0.0/255.224.0.0
no-route = 162.96.0.0/255.224.0.0
no-route = 163.0.0.0/255.192.0.0
no-route = 163.96.0.0/255.224.0.0
no-route = 163.128.0.0/255.192.0.0
no-route = 163.192.0.0/255.224.0.0
no-route = 166.96.0.0/255.224.0.0
no-route = 167.128.0.0/255.192.0.0
no-route = 168.160.0.0/255.224.0.0
no-route = 169.254.0.0/255.255.0.0
no-route = 171.0.0.0/255.128.0.0
no-route = 171.192.0.0/255.224.0.0
no-route = 172.16.0.0/255.240.0.0
no-route = 175.0.0.0/255.128.0.0
no-route = 175.128.0.0/255.192.0.0
no-route = 180.64.0.0/255.192.0.0
no-route = 180.128.0.0/255.128.0.0
no-route = 182.0.0.0/255.0.0.0
no-route = 183.0.0.0/255.192.0.0
no-route = 183.64.0.0/255.224.0.0
no-route = 183.128.0.0/255.128.0.0
no-route = 192.0.0.0/255.255.255.0
no-route = 192.0.2.0/255.255.255.0
no-route = 192.88.99.0/255.255.255.0
no-route = 192.96.0.0/255.224.0.0
no-route = 192.160.0.0/255.248.0.0
no-route = 192.168.0.0/255.255.0.0
no-route = 192.169.0.0/255.255.0.0
no-route = 192.170.0.0/255.254.0.0
no-route = 192.172.0.0/255.252.0.0
no-route = 192.176.0.0/255.240.0.0
no-route = 198.18.0.0/255.254.0.0
no-route = 198.51.100.0/255.255.255.0
no-route = 202.0.0.0/255.128.0.0
no-route = 202.128.0.0/255.192.0.0
no-route = 202.192.0.0/255.224.0.0
no-route = 203.0.0.0/255.128.0.0
no-route = 203.128.0.0/255.192.0.0
no-route = 203.192.0.0/255.224.0.0
no-route = 210.0.0.0/255.192.0.0
no-route = 210.64.0.0/255.224.0.0
no-route = 210.160.0.0/255.224.0.0
no-route = 210.192.0.0/255.224.0.0
no-route = 211.64.0.0/255.192.0.0
no-route = 211.128.0.0/255.192.0.0
no-route = 218.0.0.0/255.128.0.0
no-route = 218.160.0.0/255.224.0.0
no-route = 218.192.0.0/255.192.0.0
no-route = 219.64.0.0/255.224.0.0
no-route = 219.128.0.0/255.224.0.0
no-route = 219.192.0.0/255.192.0.0
no-route = 220.96.0.0/255.224.0.0
no-route = 220.128.0.0/255.128.0.0
no-route = 221.0.0.0/255.224.0.0
no-route = 221.96.0.0/255.224.0.0
no-route = 221.128.0.0/255.128.0.0
no-route = 222.0.0.0/255.0.0.0
no-route = 223.0.0.0/255.224.0.0
no-route = 223.64.0.0/255.192.0.0
no-route = 223.128.0.0/255.128.0.0
no-route = 224.0.0.0/224.0.0.0
```

> 不过，参考 [OpenConnect server(ocserv) 一键脚本 for deibian 7](http://www.fanyueciyuan.info/fq/ocserv-debian.html/comment-page-2) ，如果使用 openconnect 客户端，则所有版本都不支持 no-route ，可能需要使用cisco anyconnect客户端支持。所有如果使用 openconnect ，还是在客户端自己用脚本添加路由。
>
> 上述配置中，我更改了 192.168.0.0 ，因为我配置的ocserv使用了 192.168.101.0/255.255.255.0 作为 tun 网段，而我的局域网使用的是 192.168.1.0/24

```bash
192.168.0.0/255.255.255.0 ==> 192.168.1.0/255.255.255.0
```

> 此外，添加了一个VPN服务器的IP地址

**Cisco AnyConnect for BlackBerry 不支持 no-route 指令，如果服务器端配置了no-route，会导致无法通讯（显示主机无法解析或者网络未连接），所以最后还是全部删除了no-route配置。不过Cisco AnyConnect for iOS没有问题，但不确定no-route是否真正生效。** 反正手机主要是用于访问twiter，较少内网访问，所以暂时没有问题。Linux客户端采用罗有添加脚本。

> 有些IP段可能不是中国的，例如发现 m.voachinese.com 使用的akamai的CDN地址是日本的

```bash
m.voachinese.com.       1185    IN      CNAME   m.voanews.com.edgesuite.net.
m.voanews.com.edgesuite.net. 19185 IN   CNAME   a1250.b.akamai.net.
a1250.b.akamai.net.     30      IN      A       124.40.42.57
a1250.b.akamai.net.     30      IN      A       124.40.42.62
```

## 客户端添加路由脚本

默认的尚未连接VPN时候的路由表

```bash
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
default         10.33.33.250    0.0.0.0         UG        0 0          0 wlp3s0
10.33.32.0      0.0.0.0         255.255.254.0   U         0 0          0 wlp3s0
loopback        0.0.0.0         255.0.0.0       U         0 0          0 lo
```

连接VPN以后的路由表

```bash
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         0.0.0.0         0.0.0.0         U         0 0          0 tun0
0.0.0.0         10.33.33.250    0.0.0.0         UG        0 0          0 wlp3s0
10.33.32.0      0.0.0.0         255.255.254.0   U         0 0          0 wlp3s0
104.236.154.90  10.33.33.250    255.255.255.255 UGH       0 0          0 wlp3s0
127.0.0.0       0.0.0.0         255.0.0.0       U         0 0          0 lo
192.168.101.0   0.0.0.0         255.255.255.0   U         0 0          0 tun0
```

参考上述ocserv服务器端设置 no-route ，在Linux主机上，采用脚本方式设置路由。思路是使用openconnect连接了VPN服务器之后，在本地终端执行脚本 vpn\_route.sh start 设置路由（vpn\_route.sh stop则去除路由）。注意，在 cn\_route.cfg 中是需要路由的网段，类似格式如下

```bash
0.0.0.0/255.0.0.0
1.0.0.0/255.128.0.0
1.160.0.0/255.224.0.0
1.192.0.0/255.224.0.0
10.0.0.0/255.0.0.0
14.0.0.0/255.224.0.0
14.96.0.0/255.224.0.0
14.128.0.0/255.224.0.0
```

> 路由网段中去掉了

```bash
    0.0.0.0/255.0.0.0
    127.0.0.0/255.0.0.0
```

脚本 vpn\_route.sh

```bash
#!/bin/bash

DEVICE=$(ip route list | grep "^default" | grep "metric 303" | awk '{print $5}')
GATEWAY=$(ip route list | grep "^default" | grep "metric 303" | awk '{print $3}')

ROUTELIST=cn_route.cfg
ROUTENUM=$(wc -l < $ROUTELIST)

addroute()
{
COUNT=0
while [ $COUNT -lt $ROUTENUM ]
do 
    let COUNT++
    NET=`head -n $COUNT $ROUTELIST | tail -1`

    ip route add $NET via $GATEWAY dev $DEVICE
done
}

delroute()
{
COUNT=0
while [ $COUNT -lt $ROUTENUM ]
do 
    let COUNT++
    NET=`head -n $COUNT $ROUTELIST | tail -1`

    ip route del $NET via $GATEWAY dev $DEVICE
done
}

case "$1" in
        start)
                addroute && exit 0
                ;;
        stop)
                delroute && exit 0
                ;;
        *)
                echo $"Usage: $0 {start|stop)"
                RETVAL=2
esac
```

## DNSMASQ

我设置了VPN服务器上的dnsmasq，想vpn连接以后，通过查询dns来解决内网和外网的dns解析（一些内网ip解析通过dnsmasq添加），但是发现，始终不能正常访问dns。在vpn服务器上是可以解析的，但是远程不行。我使用nc检查，端口是打开的

```bash
# nc -u -v -w 2 VPN_SERVER_IP 53
li421-128.members.linode.com [VPN_SERVER_IP] 53 (domain) open
```

但是查询超时

```bash
dig @VPN_SERVER_IP www.sina.com.cn

; <<>> DiG 9.10.2-P4 <<>> @VPN_SERVER_IP www.sina.com.cn
; (1 server found)
;; global options: +cmd
;; connection timed out; no servers could be reached
```

但是在服务器上直接查询却完全正常

```bash
root@mynode:/etc# dig @VPN_SERVER_IP www.sina.com.cn

......
;; ANSWER SECTION:
www.sina.com.cn.        1728    IN      CNAME   jupiter.sina.com.cn.
jupiter.sina.com.cn.    2767    IN      CNAME   ara.sina.com.cn.
ara.sina.com.cn.        1       IN      A       58.63.236.248
ara.sina.com.cn.        1       IN      A       121.14.1.189
ara.sina.com.cn.        1       IN      A       121.14.1.190

;; AUTHORITY SECTION:
sina.com.cn.            73563   IN      NS      ns4.sina.com.cn.
sina.com.cn.            73563   IN      NS      ns1.sina.com.cn.
sina.com.cn.            73563   IN      NS      ns3.sina.com.cn.
sina.com.cn.            73563   IN      NS      ns2.sina.com.cn.
......
```

开始我以为是vpn服务影响，所以特意关闭了VPN连接，并且从其他服务器上多次测试都没有成功。也验证了没有防火墙干扰。最后，偶然搜索到 [dnsmasq: DNS request timed out for machines in local network](http://superuser.com/questions/858443/dnsmasq-dns-request-timed-out-for-machines-in-local-network) ，原来必须显式地设置 listen-address 监听接口，DNSmasq才会对外部客户端请求响应，否则只有本机（估计DNSmasq代码中检查客户端IP来判断是否是本机IP进行过滤）才提供服务，虽然端口已经监听。

修改VPN服务器上 /etc/dnsmasq.conf 配置，添加

```bash
listen-address=192.168.101.1
listen-address=VPN_SERVER_IP
```

然后重启dnsmasq就可以正常解析。

> 为了安全起见，实际我是只监听tun接口提供服务，这样只有VPN客户端可以访问DNS。

## 参考

* [Setup OpenConnect VPN Server for Cisco AnyConnect on Ubuntu 14.04 x64](https://www.vultr.com/docs/setup-openconnect-vpn-server-for-cisco-anyconnect-on-ubuntu-14-04-x64)
* [OpenConnect SERVER Setup Guide for Beginners](http://wiki.openwrt.org/doc/howto/openconnect-setup) - 在OpenWrt上部署OpenConnect服务
* [ocserv安装文档](https://gitlab.com/ocserv/ocserv)
* 其他一些中文的设置参考文档
  * [架设OpenConnect Server给iPhone提供更顺畅的网络生活](http://bitinn.net/11084/)
  * [OpenConnect server(ocserv) 一键脚本 for deibian 7+ ](http://www.fanyueciyuan.info/fq/ocserv-debian.html/comment-page-2)
  * [编译ocserv并配置Cisco AnyConnect VPN，以便在iphone上使用OpenConnect SSL VPN翻墙](http://briteming.blogspot.com/2015/02/centos-65ocservcisco-anyconnect.html)
  * [Oc­serv 在 De­bian 下的安装与配置指南](https://darknode.in/network/setup-debian-ocserv/) - 提供了有关 no-route 的建议


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://huataihuang.gitbook.io/cloud-atlas-draft/security/vpn/openconnect/deploy_ocserv_vpn_server.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
