不少自行部署OpenVPN的用户都遇到过类似问题:明明在服务端配置文件里添加了DNS推送命令,连接VPN后本地解析域名还是走运营商的DNS服务器,既可能出现解析异常,也达不到预期的流量路由效果。这类问题绝大多数都不是推送命令本身的语法错误,而是没有满足OpenVPN DNS推送:配置前提相关的核心要求,跳过前置检查直接调试命令只会浪费大量排错时间。
服务端操作系统层面的路由与转发权限前提
很多新手部署完OpenVPN服务端后,直接往配置文件里写入推送DNS的相关语句,完全没有检查服务器系统本身的转发规则是否放行DNS相关流量,这是最常见的前置疏漏。
比如在CentOS或者Debian系主流服务器系统上,首先要确认系统的ip_forward转发参数已经开启,如果这个参数处于关闭状态,所有从OpenVPN隧道转发出来的53端口DNS请求都会被系统内核直接丢弃,哪怕客户端已经成功收到推送的DNS地址,也无法向对应地址发起解析请求。
除此之外还要检查服务端本地的防火墙规则,不管是firewalld、ufw这类前端防火墙工具,还是原生iptables规则,都要放行tun或者tap虚拟网卡的53端口入站出站流量,很多默认的服务器安全规则会拦截陌生虚拟网卡发起的出站DNS请求,直接导致推送的DNS完全无法使用。
OpenVPN服务端配置文件的语法兼容前提
不同大版本的OpenVPN服务端程序,对DNS推送的语法支持存在明显差异,比如2.4版本之前的旧版本原生不支持直接推送IPv6格式的DNS地址,如果强行在老旧版本的配置文件里添加IPv6 DNS推送语句,轻则相关配置被程序直接忽略,重则导致OpenVPN服务无法正常启动。
很多人只单独添加DNS推送的命令行,忘记搭配网关重定向的配套参数,也就是配置文件里需要包含push "redirect-gateway def1 bypass-dhcp"这条规则,没有这条规则的话,客户端的默认路由不会指向OpenVPN虚拟网卡,系统发起的DNS请求还是会走本地物理网卡转发,服务端推送的DNS地址根本不会被调用。
如果部署的OpenVPN使用的是tap虚拟网卡模式,推送DNS的语法还要额外搭配对应子网的dhcp-option声明,不能直接照搬tun模式的配置语句,不然Windows系统的客户端会直接忽略收到的DNS推送报文,不会更新本地的DNS列表。
客户端侧的系统权限与网络优先级前提
在桌面端或者移动端启动OpenVPN客户端的时候,如果没有授予程序足够的系统网络修改权限,客户端就没有权限改写系统全局的DNS配置,哪怕服务端已经正常发出DNS推送报文,系统也会拒绝客户端的修改申请,继续保留本地原本的DNS设置。
以Windows系统为例,用户可以在VPN连接成功后打开网络适配器列表,找到OpenVPN生成的虚拟网卡,右键查看属性面板里的IPv4 DNS地址栏,如果这里显示为空或者还是本地原有DNS地址,就说明客户端权限不足,没有成功写入推送的DNS配置。
除此之外还要检查客户端本地有没有优先级更高的DNS锁定规则,比如企业域环境里的组策略强制锁定了全局DNS地址,或者本地安装的安全软件、DNS加速工具劫持了系统解析请求,这类场景下OpenVPN推送的DNS优先级低于本地锁定规则,自然无法生效。
配置完成后的有效性验证前提
所有OpenVPN DNS推送:配置前提都确认满足之后,不能只靠访问网页或者ping公网域名判断推送是否生效,要打开系统命令行工具执行nslookup或者dig命令,查看返回结果里的解析服务器地址,确认该地址就是你在OpenVPN服务端配置的推送DNS地址,才能说明配置完全生效。
还要避开常见的验证误区,很多客户端系统会自动缓存之前的DNS解析记录,短时间内发起相同域名的访问请求时,系统会直接调用本地缓存返回结果,不会发起新的DNS请求,验证前最好先清空本地系统的DNS缓存,再执行解析测试,避免得到误判的结果。
飞鸟加速器 
