我在 Linux 上有一个 OpenVPN 客户端,连接到 OpenVPN 服务器。服务器通过 DHCP 分配 IP,因此我使用轻敲界面而不是屯界面。
OpenVPN 连接、验证、与服务器聊天、喝杯咖啡,但却忘了打开 tap0 接口。连接后,我必须手动运行ifup tap0
以打开接口并获取 IP。
我尝试在配置文件中添加一个运行的脚本
ip link set tap0 up
dhclient tap0
但它只启动了设备,并没有获取 IP。
清理后的client.conf:
# Openvpn config to connect to <DOMAIN>
tls-client
dev tap0
; dev tap ; this didn't work either
; run script after init (supposedly)
; script-security 2 ; to run up script
; up /etc/openvpn/tap0up.sh ; bring up tap0
; up-delay ; Didn't work with or without this;
proto udp
remote <DOMAIN> 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert monkey.crt
key monkey.key
ns-cert-type server
comp-lzo
verb 3
还有 ifcfg-tap0,因为我不相信 NetworkManager
DEVICE=tap0
BOOTPROTO=dhcp
ONBOOT=yes
PEERDNS=no
ZONE=trusted
提前致谢!
编辑:有趣的事实:它将正确的静态路由添加到我的路由表中,用于它忘记启动的网络。
编辑2:OpenVPN 服务器配置,根据要求:
local <my.ext.ip>
port 1194
mode server
tls-server
proto udp
dev tap0
; dev tap
ca keys/ca.crt
cert keys/zombie.crt
key keys/zombie.key
dh keys/dh2048.pem
keepalive 10 120
comp-lzo
persist-key
persist-tun
status zombievpn-status.log
verb 3
答案1
根据我的经验,让 TAP 设备在 Ubuntu 17.10 及更高版本(以及使用 systemd-resolved 和/或网络管理器的其他操作系统)上运行良好并非易事,但经过大量实验后,我找到了一种运行良好的设置。
在描述我的解决方案之前,先介绍一下我的情况和要求。我在家庭网络中的路由器(带有 Asus Merlin 固件的 Asus RT-AC87U)上运行 OpenVPN 服务器,该路由器还运行 DHCP 服务器。DHCP 服务器配置为分发 TAP 接口的 IP,并推送 DNS 搜索域。这允许通过主机名发现连接的系统(例如,主机名为“desktop”的系统可以作为“desktop”被发现,由于搜索域为“mydomain.com”,因此扩展为“desktop.mydomain.com”)。我使用 TAP 网络,这样我就可以直接通过隧道使用局域网唤醒(局域网唤醒魔术包必须在 xxx255 地址上广播到应该唤醒系统的网络适配器的 MAC 地址,这是 TUN 设备无法做到的,因为它在错误的网络层运行,无法广播 2 级包)。服务器必须能够将 DNS 选项推送到客户端。我不希望所有互联网流量都通过隧道路由 - 这不是那种 VPN(我在另一个端口上运行单独的 TUN 服务器以用于该用例,但这超出了此答案的范围)。最后,当我关闭隧道时,我需要一切都恢复到原始状态(这不会自动发生)。
事实证明,所有的实验都很困难。最终,解决方案的配置并不复杂。我从 Ubuntu 存储库安装了 OpenVPN,撰写本文时版本为 2.4.4。
OpenVPN 服务器使用以下配置(服务器在 10.75.233.1(也是网关 IP)上运行 DNSMasq,用作 DHCP 服务器):
# Automatically generated configuration
daemon ovpn-server1
server-bridge # proxy the DHCP server
push "route 0.0.0.0 255.255.255.255 net_gateway"
proto udp
port 1194
dev tap21
ncp-ciphers AES-256-GCM
auth SHA384
comp-lzo adaptive
keepalive 15 60
verb 2
push "dhcp-option DNS 10.75.233.1" # Pushes the DNS server
tls-crypt static.key
ca ca.crt
dh dh.pem
cert server.crt
key server.key
crl-verify crl.pem
status-version 2
status status 5
# Custom Configuration
mssfix 1420 # You might not need this, it depends on your local network conditions
tun-mtu 1500 # You might not need this, it depends on your local network conditions
tls-version-min 1.2
tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384
这些都不是那么有趣。这是客户端配置:
client
dev tap0
persist-tun
persist-key
proto udp
remote mydomain.com 1194
float
ncp-ciphers AES-256-GCM
auth sha384
comp-lzo adaptive
remote-cert-tls server
auth-nocache
tls-version-min 1.2
verb 2
ca /etc/openvpn/secrets/mydomain/ca.crt
cert /etc/openvpn/secrets/mydomain/client.crt
key /etc/openvpn/secrets/mydomain/client.key
tls-crypt /etc/openvpn/secrets/mydomain/ta.key
resolv-retry infinite
nobind
这也不是那么有趣,除了一件事——没有上/下脚本 [blow mind gif here]。
这样做的原因是,我认为让现有的操作系统服务尽可能地处理是最优雅的做法——换句话说,顺应操作系统的脉络而不是违背它。安装的默认启动/关闭脚本用于操作/etc/resolv.conf
,Ubuntu 18.04 不再(直接)使用。它使用 systemd-resolved。直接操作 resolv.conf 会导致许多泪水,年轻的绝地武士。然而,这并没有导致 Ubuntu 开发人员默认为 systemd-resolved 安装启动/关闭脚本。这取决于你(sudo apt install openvpn-systemd-resolved
——脚本将位于/etc/openvpn
)。根据我的经验,它们适用于 TUN 设备,但也不能正确完成 TAP 设备的工作。
效果非常好的是,明确将 tap0 设备添加到您的网络接口(/etc/network/interfaces
):
# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback
allow-hotplug tap0
iface tap0 inet dhcp
使用以下命令重新启动网络堆栈:
sudo systemctl daemon-reload
sudo systemctl restart networking
砰!操作系统现在将自行查询 DHCP 服务器并启动适配器,就像普通接口一样。当您连接到服务器时,ifconfig tap0
应该会显示一个分配了 IP 地址的适配器。此外,systemd-resolve --status
在输出的第一行应该会显示 OpenVPN 服务器推送的 DNS 搜索域和 DNS 服务器已设置为全局配置,并且快速操作nslookup desktop
现在应该可以正常工作(前提是主机存在于隧道另一侧的某个地方)。
然而,当您关闭隧道时,这会导致一些问题。它关闭得很好,并且 tap0 设备在 ifconfig 输出中不再可见。但是,这将向systemd-resolve --status
您显示您的搜索域和 DNS 服务器在很大程度上继续成为您存在的一部分。就我而言,因为我运行 VPN 服务器的域是“mydomain.com”,而搜索域也是“mydomain.com”,这导致我在隧道关闭后无法再次连接到 VPN 服务器,因为只要 systemd-resolved 仍然对讨厌的搜索域感到困惑,它的实际 IP 就无法再解析。重新启动 systemd-resolved 服务并不能解决问题,但重新启动可以。哦,致命的痛苦!
值得庆幸的是,这个问题也有解决办法。原来,在 处创建了一个临时配置文件,/run/systemd/resolved.conf.d/isc-dhcp-v4-tap0.conf
导致 systemd-resolved 顽固地连接到我的 VPN 服务器的 DNS 服务器。删除该文件然后重新启动服务即可解决问题 ( sudo rm /run/systemd/resolved.conf.d/isc-dhcp-v4-tap0.conf && sudo systemctl restart systemd-resolved.service
)。
因此,对于基本设置,这已经足够了。但是,我喜欢这种奢侈,我们可以使用一个不错的 systemd 服务来为我们提供它!请注意,使用 Ubuntu 的 OpenVPN 包,所有 OpenVPN 配置都可以使用“通配符”systemd 服务/etc/openvpn/client
。您可以查看位于 的单元文件。它可以通过 进行控制。它完全适用于 TUN 样式的隧道,所以不要管它。我们将复制它以用于 TAP 设备。/lib/systemd/system/[email protected]
sudo systemctl start [email protected]
创建文件/lib/systemd/system/openvpn-my-tap-service-name.service
并添加:
[Unit]
Description=OpenVPN tunnel for mydomain.com
After=syslog.target network-online.target
Wants=network-online.target
Documentation=man:openvpn(8)
Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO
[Service]
Type=notify
PrivateTmp=true
WorkingDirectory=/etc/openvpn/client
ExecStart=/usr/sbin/openvpn --suppress-timestamps --nobind --config mydomain.com.conf
ExecStopPost=/etc/openvpn/post-tap0-service-stop.sh # Removes search domain and DNS server from systemd-resolved config
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE
LimitNPROC=10
DeviceAllow=/dev/null rw
DeviceAllow=/dev/net/tun rw
ProtectSystem=true
ProtectHome=true
KillMode=process
[Install]
WantedBy=multi-user.target
这是默认服务的简单改编。要使其工作,您的客户端配置必须位于/etc/openvpn/client/mydomain.com.conf
。只添加了一件事 - 一个小脚本来删除“临时”的 systemd 解析配置文件。
创建文件/etc/openvpn/post-tap0-service-stop.sh
并将其设置为可执行(使用chmod +x /etc/openvpn/post-tap0-service-stop.sh
):
#!/bin/bash
FILE_MESSING_WITH_SYSTEMD_RESOLVED=/run/systemd/resolved.conf.d/isc-dhcp-v4-tap0.conf
echo "Removing $FILE_MESSING_WITH_SYSTEMD_RESOLVED..."
rm -f $FILE_MESSING_WITH_SYSTEMD_RESOLVED
echo "Restarting systemd-resolved service..."
systemctl restart systemd-resolved.service
好了!现在您可以使用它来控制 OpenVPN 了sudo systemctl start/stop/restart/status openvpn-my-tap-service-name
(sudo systemctl daemon-reload
当然,是在创建服务文件之后)。
只剩最后一步了。一直用密码控制服务很麻烦。我们可以通过将控制服务所需的命令添加到 sudoers 文件来解决这个问题。
执行以下命令pkexec visudo -f /etc/sudoers.d/openvpn
并输入以下内容:
Cmnd_Alias OPENVPN = /bin/systemctl start openvpn-my-tap-service-name, \
/bin/systemctl stop openvpn-my-tap-service-name, \
/bin/systemctl restart openvpn-my-tap-service-name
%my-username ALL= NOPASSWD: OPENVPN
现在您可以sudo systemctl
无需密码执行您的服务命令。
希望这会有帮助!
答案2
我也遇到过这种奇怪的情况。Openvpn 一直运行良好,直到我做了以下三项更改,试图禁用 openvpn dhcp 服务器并使用我自己的(桥接/tap 模式),但失败了。也许在你的情况下,你可能需要对配置应用相反的更改(添加服务器指令、删除 tls-server 和服务器 xy)。
- 在服务器配置中,我注释掉了该
server X Y
指令 - 在服务器配置中,我添加
tls-server
并mode server
注释掉了一个 IP 池选项,所有这些都是为了响应在启动 openvpn 时收到的致命错误消息,而无需server x y