Ubuntu 14.04 升級到 16.04 後未載入 iptables 模組

Ubuntu 14.04 升級到 16.04 後未載入 iptables 模組

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

相關內容