因此,我決定給 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 系統的受歡迎的更新。