你好
背景:
我正在创建一个针对Linux系统的OpenVPN包装应用程序,该应用程序已接近完成。我遇到了一些小问题。
OpenVPN需要root访问权限来修改路由表(添加和删除路由)。这里情况变得有些模糊和令人困惑。
希望通过扩展此问题,共享一些行业标准答案和解决方案。
文档:
所以,经过数小时的搜索,我编制了一个可能获得root访问权限的方法清单,但是没有任何官方信息或真正的指导可以获取此SU特权。
让我们考虑以下方法。
1. 使用pkexec & polkits
请在此处找到官方freedesktop polkit文档,并在此处获取有关最佳实践的一些信息。
在线上可以找到一些使用pkexec和polkits的教程 - 此处,这帮助我创建了我的polkit文件。 - SO Thread - 还有一个针对Qt应用程序的可爱的小教程
简要解释一下(我的理解)关于pkexec
和polkits
:
polkits
:
polkits由操作和规则组成(详见文档以进行深入阅读和解释)。它定义了应用程序的操作和与之相关联的规则。规则可以被定义为属于特定组的用户,其中操作查询规则,如果它已成功通过规则,则用户会自动验证(无需弹出密码提示),否则他们需要输入管理员密码
pkexec
:
一个用于与polkit操作接口并认证应用程序以获取root访问权限的应用程序。
这些需要将操作添加到/usr/share/polkit-1/actions/
和/usr/share/polkit-1/rules.d/
(以及其他目录,请参见文档中的所有位置)
这种方法似乎被广泛使用(但需要更多解释才能容易理解,依我之见)
注意:可使用qt-polkit
库,详见其GitHub仓库
简短版TL;DR,请参见此处
我创建的polkit文件(请注意,这可能不正确,但适用于我):
可以找到/添加的位置(还有其他位置)
/usr/share/polkit-1/actions
策略工具文件名:
com.myappname.something.policy // .policy
必须包含在内
注意:
com.myappname.something
“命名空间”是指策略的名称(阅读文档时,这一点可能不太清楚)。
Policy Kit 内容
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD polkit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/software/polkit/policyconfig-1.dtd">
<policyconfig>
<vendor>My App Name</vendor>
<vendor_url>http://myappurl.com/</vendor_url>
<action id="com.myappname.something.myaction-name">
<description>Run the polkit for My App which requires it for X usage</description>
<message>My App requires access to X, which requires root authentication, please let me have su access</message>
<icon_name>myappname</icon_name>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
<annotate key="org.freedesktop.policykit.exec.path">/usr/bin/myappname</annotate>
<annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
</action>
</policyconfig>
关于我的策略文件的注释(重要部分)
- 这只是一个示例,请参阅文档以获取官方示例和描述:
<vendor>My App Name</vendor>
是应用程序名称,可以包含空格<action id="com.myappname.something.myaction-name">
这里可以填写任何操作名称。注意! 文件名为 ->
com.myappname.something.policy
,action id
为 ->com.myappname.something.myaction-name
应具有相同的命名空间。图标名称应符合最新的 freedesktop 图标规范,可在此处找到。
TL;DR(或者不想读太多): 图标位置在:
1. /home/yourusername/.icons (sometimes not there)
2. /home/yourusername/.local/share/icons
2. /usr/share/icons
只要它们符合大小并且是PNG格式,您可以仅传递文件名(省略格式)。
Very Important
:<annotate key="org.freedesktop.policykit.exec.path">/usr/bin/myappname</annotate> <annotate key="org.freedesktop.policykit.exec.allow_gui">true</annotate>
pkexec <myappname>
时,如果没有以下这些行(老实说,我不太确定它们的目的),你会遇到类似于以下错误的问题:2017-12-19 12::58:24 Fatal: QXcbConnection: Could not connect to display ((null):0, (null))
Aborted (core dumped)
注意:保持
key
不变,但您可以并且可能应该将exec.path
关键字更改为您的应用程序位置。
策略工具包是如何工作的?
简而言之,如果您查看之前提到的可爱的示例(并跳过所有非常相似的文件名称),就会变得清晰明了。当一个人运行时:
pkexec <myappname>
这将调用本地认证代理以root的身份运行应用程序(在我们的情况下)。
这是由上面提到的actions
(策略工具包)处理的。此外,规则利用action id
执行其他查询等操作,可以在上面提供的示例中查看。
一旦输入了管理员密码,根据在默认设置中输入的“设置”(请参见此处),我们有:
auth_admin_keep
类似于auth_admin,但授权只保留一段时间(例如5分钟)。
因此,在我的OpenVPN应用程序中,用户可以连接到OpenVPN连接,直到再次请求密码的下一个5分钟。
2. Sudo
(/etc/sudoers):
这似乎是大多数需要root访问权限的用户使用的方法,但不建议这样做:
例如,通过带有参数的singleShot QProcess
调用来运行主应用程序之前检查root访问权限:
/bin/sh -c sudo -v
如果你在各种Linux发行版中使用此命令,将会导致退出代码为1
(因此我需要寻找替代方案)。
3. setuid():
这里可以找到一个非常好的示例,但不幸的是,它似乎在现代Linux发行版上无法正常工作,因为它是一个易于被利用的安全漏洞。
简而言之,该过程要求:
chmod +x <executable>
同时检查应用程序中是否设置了s
位,并使用getuid()
获取用户ID和getgid()
获取用户组ID来进行验证。
这些函数可以在Linux头文件中找到,定义如下:
<sys/types.h> // defines structs
<unistd.h> // defines methods
然而,这似乎在现代Linux系统中无法正常工作。以下是以普通用户身份运行具有设置了
s
位的根拥有的应用程序的输出:2017-12-19 12::21:08 Fatal: FATAL: The application binary appears to be running setuid, this is a security hole. ((null):0, (null))
Aborted (core dumped)
告别setuid()
4. 其他方法:
- PAM
更多阅读请参见
- 手册页
- 教程/解释
关于跨平台 PAM 集成的 QT 论坛问题
QT usermode
Qt 提供了一个获取 root 访问权限的小实现,但仅适用于使用yum
包管理器的 Linux 发行版。
此问题的后续问题,请参见 这个 QT 论坛问题
问题:
上述内容可能只包括获取 root 访问权限的一小部分可用方法,然而考虑到一些应用程序在全球范围内使用,它们经常受到攻击或分解甚至被破坏。
进行这项研究后,我的知识得到了扩展,但并没有给出推荐的确切方法,只是提供了一些提示。
问题:
在工业界中哪种方法优先使用,即何时应该使用其中一种(PAM vs polkits vs 简单的 sudo),如果有其他方法可用,那么这些方法是否更受欢迎?