因此,我决定给 Ubuntu 16.04 一个机会,尽管我对 systemd 的看法稍显不利。
升级后,我之前的持续 OpenVPN 连接不再工作。幸运的是,系统日志对于指出根本原因非常有帮助。
openvpn-up: + /sbin/iptables -t nat -D POSTROUTING -o tun0 -s 192.168.x.x -j SNAT --to-source 10.x.x.x
openvpn-up: modprobe: ERROR: could not insert 'ip_tables': Operation not permitted
openvpn-up: iptables v1.6.0: can't initialize iptables table `nat': Table does not exist (do you need to insmod?)
openvpn-up: Perhaps iptables or your kernel needs to be upgraded.
openvpn-up: + /sbin/iptables -t nat -A POSTROUTING -o tun0 -s 192.168.x.x -j SNAT --to-source 10.x.x.x
openvpn-up: modprobe: ERROR: could not insert 'ip_tables': Operation not permitted
openvpn-up: iptables v1.6.0: can't initialize iptables table `nat': Table does not exist (do you need to insmod?)
ovpn-conn[613]: WARNING: Failed running command (--up/--down): external program exited with error status: 3
openvpn-up: Perhaps iptables or your kernel needs to be upgraded.
ovpn-conn[613]: Exiting due to fatal error
注意:这些openvpn-up
是通过取消脚本第二行的注释来生成的/etc/openvpn/openvpn-up.sh
(行读取:)exec &> >(logger -s -t openvpn-up) && set -x
。
嗯,由于某种原因ip_tables
无法加载模块。在确保内核模块全部存在后apt-get install --reinstall linux-image-$(uname -r)
,我尝试使用modprobe ip_tables
,果然看到它现在已加载,lsmod
而且还在系统日志中:
kernel: [ 446.293882] ip_tables: (C) 2000-2006 Netfilter Core Team
果然,在systemctl restart openvpn
此之后运行时,它似乎打开了连接,并且iptables-save
输出证明已添加了适当的 SNAT 规则。
我的猜测现在 OpenVPN 单元是在某些没有足够权限使用modprobe
等的用户上下文中执行的。
不过,我一直无法证实这个怀疑。事实上,它的输出systemctl cat openvpn
让我很困惑:
# systemctl cat [email protected]
# /lib/systemd/system/[email protected]
[Unit]
Description=OpenVPN connection to %i
PartOf=openvpn.service
ReloadPropagatedFrom=openvpn.service
Before=systemd-user-sessions.service
Documentation=man:openvpn(8)
Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage
Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO
[Service]
PrivateTmp=true
KillMode=mixed
Type=forking
ExecStart=/usr/sbin/openvpn --daemon ovpn-%i --status /run/openvpn/%i.status 10 --cd /etc/openvpn --script-security 2 --config /etc/openvpn/%i.conf --writepid /run/openvpn/%i.pid
PIDFile=/run/openvpn/%i.pid
ExecReload=/bin/kill -HUP $MAINPID
WorkingDirectory=/etc/openvpn
ProtectSystem=yes
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_AUDIT_WRITE
LimitNPROC=10
DeviceAllow=/dev/null rw
DeviceAllow=/dev/net/tun rw
[Install]
WantedBy=multi-user.target
有没有能力我需要使脚本能够成功调用insmod
/ modprobe
?我想避免添加,CAP_SYS_ADMIN
因为这看起来相当粗糙。或者是ip_tables
通过将 a 放入 来加载模块的.conf
唯一方法/etc/modprobe.d
?
本质上我要问的是:Ubuntu 16.04(它有不是从14.04升级)完成这个任务吗?即规范是什么(和规范)这样做的方式?最后但并非最不重要的一点是,我如何确定特定单元在哪个用户上下文中运行(或者更准确地说:具有哪些功能)?
答案1
任何 systemd 指令的文档都可以通过 查找man system.directives
。从那里,我发现CapabilityBoundingSet=
记录在man systemd.exec
.
这让我找到了man 7 capabilities
记录不同功能的地方。通过在那里搜索“模块”,我发现了这个,这听起来像是您需要的功能:
CAP_SYS_MODULE 加载和卸载内核模块
目前还不清楚为什么默认情况下不包含此功能。也许 OpenVPN 的常见用例不需要它。
将此功能添加到包的 systemd 配置中的最小方法是使用“插入单元”。创建这个文件:
/etc/systemd/system/[email protected]/add-module-loading.conf
有了这个内容:
[Service]
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH CAP_AUDIT_WRITE CAP_SYS_MODULE
这将利用现有功能来扩展服务CAP_SYS_MODULE
。
我也曾犹豫过,systemd
但发现了很多喜欢的东西。该timer
系统是对已有 20 年(多)年历史的 cron 系统的一个受欢迎的更新。