分类 技术 下的文章

本文介绍如何使用 rpm-ostree 查找要添加到基于 ostree 的系统(例如 Silverblue 和 Kinoite)的应用。

基于 Fedora ostree 的系统的主要优点之一是系统的不可变性。该镜像不仅是只读的,而且是预先构建在 Fedora 服务器上的。因此,更新正在运行的系统会下载更新增量(即仅差异)并修补系统。这使得许多安装在默认情况下都是相同的。

对于大多数人来说,预构建的镜像就足够了,因为通常鼓励用户同时使用 Flatpak 安装应用,使用工具箱进行开发任务。但是,如果特定应用不符合此要求并且用户需要在主机系统上安装应用怎么办?

在这种情况下,可以选择在系统上覆盖软件包,在本地创建一个新的镜像,在标准镜像上添加软件包。

但是,我如何知道我要安装哪个包?搜索功能怎么样?

老方法(toolbox + dnf search)

虽然始终可以通过支持 PackageKit 的软件中心(例如 GNOME “ 软件 Software ” 应用 或 KDE “ 发现 Discover ” 应用)搜索软件包,但通过 CLI 来搜索软件包有点困难。

由于 rpm-ostree 不曾提供搜索命令,因此常见的搜索方式是使用 toolbox enter 进入工具箱并使用 dnf search <搜索词> 进行搜索。这样做的缺点是需要在工具箱中启用相同的仓库才能获得正确的搜索结果。

搜索 neofetch 的示例:

$ toolbox enter
<Note that at this point the toolbox command might request creating a toolbox, which might involve downloading a container image>
⬢[fedora@toolbox ~]$ dnf search neofetch
<snip> 
=== Name Exactly Matched: neofetch ===
neofetch.noarch : CLI system information tool written in Bash
=== Summary Matched: neofetch ===
fastfetch.x86_64 : Like neofetch, but much faster because written in c

新方法(rpm-ostree search)

version 2023.6 开始,rpm-ostree 支持 search 命令,允许用户使用 rpm-ostree 搜索可用的软件包。一个示例命令是:

rpm-ostree search *kernel

要使用搜索命令,请首先确保你使用的是 rpm-ostree 2023.6 或更高版本:

$ rpm-ostree --version
rpm-ostree:
    Version: '2023.8'
    Git: 9a99d0af32640b234318815a256a2d11e35fa64c
    Features:
    - rust
    - compose
    - container
    - fedora-integration

如果满足版本要求,你应该能够运行 rpm-ostree search <搜索词>

这是一个使用 rpm-ostree search 搜索 neofetch 的示例:

$ rpm-ostree search neofetch

===== Name Matched =====
neofetch : CLI system information tool written in Bash

===== Summary Matched =====
fastfetch : Like neofetch, but much faster because written in c

(题图:DA/5d27838e-6068-46a6-9bca-4ec486d65c46)


via: https://fedoramagazine.org/searching-for-packages-with-rpm-ostree-search/

作者:Mateus Rodrigues Costa 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

就算你是素食主义者或对海鲜有过敏反应,也值得试试 Fish ?

Bash 是使用最广泛的 Shell,Zsh 则是开发者圈里最受青睐的,但 Fish 往往被许多人忽视。

这绝非夸张之辞。Fish 的确是个备受忽视的 Shell,它对新手和资深的自由开源软件用户,都可能是极好的选择。

Fish 提供了一系列吸引人的功能,使其具有鲜明优势。这其中包括了从语法高亮到缩写(我个人最喜欢的部分),这里面充满了种种新奇。

下面,我要和大家分享一些我最青睐的 Fish Shell 特性。

1、语法高亮

在错误的命令被执行之前就识别出它们将大大节省你的时间,同时降低你的挫败感。

现代的许多代码编辑器都内置了语法高亮功能,而 Fish 不仅将此功能内置在了 Shell 中,而且对于 Linux 命令也同样有效。

命令有误?你会发现其被红色高亮。同样的,对于不符合上下文的参数和选项也是如此。

错误高亮为红色

2、自动建议

当你输入命令时,Fish Shell 会自动推荐命令,然后你可以按照提示,使用 Tab 键进行相应的补全操作。

Fish 自动补全

随着你的输入,建议会以灰色显示,使其更易于识别。如果整条建议都对你的胃口,你可以按右箭头键来完成整个命令的补全

3、命令选项的交互式手册页

这是一个炫酷的功能,你可以交互性地参考手册页完成命令选项的填写。

首先,你需要先解析手册页,这可以通过以下命令来完成:

fish_update_completions

这会对手册页进行解析。

手册页解析

现在,如果你输入一个命令,添加连字符作为选项,然后按下 Tab 键,就能看到手册页给出的可能选项及其简短描述:

Fish 手册页帮助

你可以通过滚动一览这些选项,并在阅读了作用说明后,从弹出的分页器中进行选择。

要比直接输入 command -h 更便利一些对吧。

4、缩写优于别名

在 Fish 里,缩写的作用就如同文本扩展工具。你可以为一些常用的代码设置易于调用的缩写。

比如说,我把 sch 设为 pacman -Ss 的缩写,用以搜索软件包。

abbr -a sch pacman -Ss

于是,每次我输入 sch 并按空格键后,它就会被替换成 pacman -Ss

Fish Shell 缩写

你甚至可以把它写入配置文件,让其成为永久设置。

? 别名和缩写的关键区别在于,别名的工作是内部完成的,你看不到其背后真正运行的命令。而缩写不仅会展示实际的命令,而且会让它们在历史记录里也正确地出现。

5、丰富的基于 Web 的帮助

Linux 纯粹主义者常常依赖手册页来寻求命令帮助,而新一代的 Linux 用户则更多地依赖网络资源。

Fish 则结合了这两者优点,提供了详尽的“基于 Web 的帮助”功能,并且且易于使用,即便在无网络连接的情况下也同样可用,因为它是本地化存储的。

在运行 Fish Shell 时,仅需输入:

help

就可以在你的网络浏览器上打开帮助页面了。

Fish Shell 网页帮助

如今,你可以随时方便地查阅这份详细的文档。

6、基于 Web 的配置

没错,这是另一个“基于 Web”的功能。

要改变提示符颜色或其他配置,你不必在终端里编辑配置文件,相反地,你可以运行基于 Web 的配置。

在运行 Fish Shell 时,只需输入以下命令:

fish_config

这会打开你的浏览器,并显示出配置设置。

Fish Shell 基于 Web 的配置

在这里,你可以更改颜色,从现有列表中选择一个不同的提示符等等。

提示符选择

通过这种方式来改变配置更方便,对吗?

7、自动切换目录

如果你想切换到某个目录,你不需要输入 cd 命令。只需要键入该目录名称就行了。

例如,如果你位于主目录,并希望切换到 Downloads 目录,只需要输入 Downloads。输入过程中,它会进一步给出补全建议。

自动 cd

如果你正在某个特定目录中,想要跳转到一个完全不同的路径,则需要使用绝对路径。

8、更简洁的路径导航

如果你需要在浏览过的目录之间来回切换,没必要输入路径或使用 cd .. 等。只要ALT + ←ALT + →,分别向前和向后移动就行了。

目录导航

或者,你可以键入 cdh 并按回车,这会呼出一个分页器界面,你可以使用对应的数字来回到你想去的目录。

使用分页器导航

9、交互式历史搜索

你可以在 Fish 中交互式地搜索某个特定的历史命令。做这个的时候,就使用我们熟悉的 CTRL+R 就行了。

这会呼出一个类似于分页器的界面,显示一个搜索提示。输入你想要查找的命令,就能看到搜索结果:

交互式历史搜索

10、全局变量

在 Fish Shell 中,如果你将一个变量设置为全局的,那么它将在重启 Shell 或者重启系统后仍然可用。

要设置一个全局变量,可以使用:

set -U my_variable 10

这时,my_variable 的值将会被设置为 10,即使系统重启后也不变。

是的,不需要将它们添加到你的 RC 或 profile 中。

11、隐私模式

Fish Shell 有一个隐私模式,该模式下输入的命令将不会被保存到历史记录或存储在硬盘上。

要进入隐私模式,使用命令:

fish -P

Fish 隐私模式

工作完成后,通过键入 exit 就可以退出隐私模式。

Fish 还有更多你可以探索的

Fish Shell 提供了许多其他的用户友好特性,比如:

  • 使用 ALT+Enter 实现简单的多行命令编辑
  • 切换 Emacs(默认)/Vim 键位绑定
  • 提供简洁明了的脚本编写语法

当然,你可以在其他 Shell 中通过一些努力实现大部分 Fish Shell 的特性,但默认启用这些特性可就完全是另一回事了。

Fish 可以帮助你在掌控开发环境的前提下,提高开发工作的效率。别把为 Fish Shell 编写脚本运行在 Bash 中,在多用户系统的共享环境中可能会引发 Shell 兼容性问题。

如果你喜欢这些特性,试试 Fish Shell 看看效果如何。也许你会将 Fish 设为 你的默认 Shell

即使你不想在终端里看到 “Fish”,也许你会喜欢 ASCII 水族馆 ?

在 Linux 终端利用 Asciiquarium 打造海底世界

? 请在评论中分享你对 Fish Shell 的看法 ?

(题图:DA/8522d28f-40ab-4eaa-b2b5-bc627f114224)


via: https://itsfoss.com/fish-shell-features/

作者:Abhishek Prakash 选题:lujun9972 译者:ChatGPT 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在本系列的 上一篇文章 中,我们进一步讨论了矩阵和线性代数,并学习了用 JupyterLab 来运行 Python 代码。在本系列的第四篇文章中,我们将开始学习 TensorFlow,这是一个非常强大的人工智能和机器学习库。我们也会简要介绍一些其它有用的库。稍后,我们将讨论概率、理论以及代码。和往常一样,我们先讨论一些能拓宽我们对人工智能的理解的话题。

到目前为止,我们只是从技术方面讨论人工智能。随着越来越多的人工智能产品投入使用,现在是时候分析人工智能的社会影响了。想象一个找工作的场景,如果你的求职申请由人来处理,在申请被拒绝时,你可以从他们那里得到反馈,比如被拒的理由。如果你的求职申请由人工智能程序处理,当你的申请被拒绝时,你不能要求该人工智能软件系统提供反馈。在这种情况下,你甚至不能确定你的申请被拒绝是否确实是仅基于事实的决定。这明确地告诉我们,从长远来看,我们需要的不仅仅是魔法般的结果,还需要人工智能具有 责任 accountability 保证 guarantee 。(LCTT 译注:责任主要指确保系统的决策过程是透明的、可解释的,并且对系统的行为负责。保证是指对于系统性能指标和行为的一种承诺或者预期。)目前有很多试图回答这些问题的研究。

人工智能的应用也会引发许多道德和伦理上的问题。我们不必等到强人工智能(也被称为 通用人工智能 artificial general intelligence —— AGI)出现才研究它的社会影响。我们可以通过思想实验来探究人工智能的影响。想象你在一个雨夜你驾车行驶在有发夹完的道路上,突然你眼前有人横穿马路,你的反应是什么?如果你突然刹车或转向,你自己的生命将处于极大的危险之中。但如果你不这样做,过马路的人恐怕凶多吉少。因为我们人类具有自我牺牲的特质,在决策的瞬间,即使是最自私的人也可能决定救行人。但我们如何教会人工智能系统模仿这种行为呢?毕竟从纯粹的逻辑来看,自我牺牲是一个非常糟糕的选择。

同样的场景下,如果汽车是由人工智能软件在驾驶会发生什么呢?既然你是汽车的主人,那么人工智能软件理应把你的安全放在首位,它甚至全不顾其他乘客的安全。很容易看出,如果世界上所有的汽车都由这样的软件控制的话将导致彻底的混乱。现在,如果进一步假设乘坐自动驾驶汽车的乘客身患绝症。那么对于一个数学机器来说,为了行人牺牲乘客是合乎逻辑的。但对于我们这些有血有肉的人却不见得如此。你可以花点时间思考一下其它场景,注重逻辑的机器和热血的人类都会做出什么样的决策。

有很多书籍和文章在讨论人工智能全面运作后的政治、社会和伦理方面的问题。但对于我们这些普通人和计算机工程师来说,读所有的书都是不必要的。然而,由于人工智能的社会意义如此重要,我们也不能轻易搁置这个问题。为了了解人工智能的社会政治方面,我建议你通过几部电影来理解人工智能(强人工智能)如何影响我们所有人。 斯坦利·库布里克 Stanley Kubrick 的杰作《 2001:太空漫游 2001: A Space Odyssey 》是最早描绘超级智能生物如何俯视我们人类的电影之一。这部电影中人工智能认为人类是世界最大的威胁,并决定毁灭人类。事实上,有相当多的电影都在探索这种情节。由伟大的艺术大师 史蒂文·斯皮尔伯格 Steven Spielberg 亲自执导的《 人工智能 Artificial Intelligence 》,探讨了人工智能机器如何与人类互动。另一部名为《 机械姬 Ex Machina 》的电影详细阐述了这一思路,讲述了具有人工智能的机器。在我看来这些都是了解人工智能的影响必看的电影。

最后思考一下,试想如果马路上的汽车使用来自制造商的不同的自动驾驶规则和人工智能,这将导致彻底的混乱。

TensorFlow 入门

TensorFlow 是由 谷歌大脑 Google Brain 团队开发的一个自由开源的库,使用 Apache 2.0 许可证。TensorFlow 是开发人工智能和机器学习程序的重量级的库。除了 Python 之外,TensorFlow 还提供 C++、Java、JavaScript 等编程语言的接口。在我们进一步讨论之前,有必要解释一下 张量 tensor 是什么。如果你熟悉物理学,张量这个词对你来说可能并不陌生。但如果你不知道张量是什么也不用担心,现阶段把它看作多维数组就行了。当然,这是一种过度简化的理解。TensorFlow 可以在 NumPy 提供的多维数组之上运行。

首先,我们要在 JupyterLab 中安装 TensorFlow。TensorFlow 有 GPU 版本和 CPU 版本两种安装类型可以选择。这主要取决于你的系统是否有合适的 GPU。GPU 是一种利用并行处理来加快图像处理速度的电路。它被广泛用在游戏和设计领域,在开发人工智能和机器学习程序时也是必不可少的硬件。但一个不太好的消息是 TensorFlow 只兼容英伟达的 GPU。此外,你需要在系统中安装一个称为 CUDA( 计算统一设备架构 compute unified device architecture )的并行计算平台。如果你的系统满足这些要求,那么在 JupyterLab 上执行命令 pip install tensorflow-gpu 来安装 GPU 版本的 TensorFlow。如果你系统的 GPU 配置无法满足要求,当你尝试使用 TensorFlow 时,会得到如下错误消息:“CUDA\_ERROR\_NO\_DEVICE: no CUDA-capable device is detected”。此时使用 pip uninstall tensorflow-gpu 卸载 GPU 版本的 TensorFlow。然后执行命令 pip install tensorflow 安装 CPU 版本的 TensorFlow。现在 TensorFlow 就准备就绪了。请注意,目前我们将讨论限制在 CPU 和 TensorFlow 上。

图 1:第一个使用 TensorFlow 的 Python 脚本

现在,让我们运行第一个由 TensorFlow 驱动的 Python 代码。图 1 显示了一个简单的 Python 脚本及其在 JupyterLab 上执行时的输出。前两行代码将库 NumPy 和 TensorFlow 导入到 Python 脚本中。顺便一提,如果你想在 Jupyter Notebook 单元中显示行号,单击菜单 “ 查看 View > 显示行号 Show Line Numbers ”。第 3 行使用 NumPy 创建了一个名为 arr 的数组,其中包含三个元素。第 4 行代码将数组 arr 的每个元素乘 3,将结果存储在一个名为 ten 的变量中。第 5 行和第 6 行分别打印变量 arrten 的类型。从代码的输出中可以看到,arrten 的类型是不同的。第 7 行打印变量 ten 的值。注意,ten 的形状与数组 arr 的形状是相同的。 数据类型 int64 在本例中用于表示整数。这使得本例中 NumPy 和 TensorFlow 数据类型之间的无缝转换成为可能。

TensorFlow 支持很多操作和运算。随着处理的数据量的增加,这些操作会变得越来越复杂。TensorFlow 支持常见的算术运算,比如乘法、减法、除法、幂运算、模运算等。如果参与运算的是列表或元组,TensorFlow 会逐元素执行该操作。

图 2:TensorFlow 中的逐元素操作

TensorFlow 还支持逻辑运算、关系运算和位运算。这里的操作也是按元素执行的。图 2 显示了执行这些按元素操作的 Python 脚本。第 1 行代码从列表创建一个张量,并将其存储在变量 t1 中。TensorFlow 的函数 constant() 用于从 Python 对象(如列表、元组等)创建张量。类似地,第 2 行创建了另一个张量 t2。第 3 行和第 4 行都是执行逐元素求幂并打印输出。从图 2 中可以清楚地看出,该求幂的结果是相同的。第 5 行代码比较张量 t1t2 的元素并打印结果。输出中的 [True True False] 分别是对应 3>2、4>3 和 2>6 的结果。第 6 行的输出与之类似。

图 3:TensorFlow 矩阵乘法

图 3 展示了 TensorFlow 处理矩阵的例子。第 1 行和第 3 行分别构造两个矩阵 xy,第 2 行和第 4 行分别打印矩阵 xy的形状。代码的输出显示 x 的形状为 (3,3)y 的形状为 (3,)。从本系列前面介绍的矩阵知识,我们知道这两个矩阵是不能相乘的。

因此,在第 5 行中将矩阵 y 增加了一个维度。在第 6 行,再次打印矩阵 y 的形状,输出结果为 (3,1)。现在矩阵 xy 可以相乘了。第 7 行中,将矩阵相乘并打印输出。注意,类似的操作也可以在张量上执行,即使张量的维数很高,TensorFlow 也可以很好地扩展。在本系列的后续文章中,我们将更多地了解 TensorFlow 支持的数据类型和其他复杂操作。

既然介绍了 TensorFlow,我想我也应该提一下 Keras。它为 TensorFlow 提供 Python 接口。在后续的文章中,我们将专门介绍 Keras。

我们如何利用非英伟达 GPU 的能力呢?有许多功能强大的软件包可以做到这一点。比如 PyOpenCL,一个在 Python 中编写并行程序的框架。它让我们可以使用 OpenCL( 开放计算语言 open computing language )。OpenCL 可以与 AMD、Arm、英伟达等厂商的 GPU 进行交互。当然还有其他选择,比如 Numba。它是一种JIT 编译器,可用在代码执行期间将 Python 代码编译为机器码。如果 GPU 可用,Numba 允许代码使用的 GPU 能力。图 4 是展示了使用 Numba 的 Python 代码。

我们可以看到函数 fun() 具有允许并行化的特征。从图 4 中可以看到,代码在不使用和使用 Numba 的情况下的答案是相同的。但是我们可以看到所花费的执行时间是不同的。当使用 Numba 并行化代码时,只花费了不到一半的时间。此外随着问题规模的增加,并行化和非并行化版本所花费的时间之间的差距也将增加。

图 4:使用 Numba 进行并行化

SymPy 入门

SymPy 是一个用于符号计算的 Python 库。通过图 5 中的例子,让我们试着理解什么是符号计算。它使用 SymPy 提供的函数 Integral()来求积分。图 5 也显示了这个符号计算的输出。注意,SciPy 提供的 integrate() 函数返回数值计算结果,而 SymPy 的 Integral() 函数能提供精确的符号结果表达式。人工智能和机器学习程序开发中会用到一些统计学操作,SymPy 在执行这些操作时非常有用。

图 5:符号计算的例子

在本系列的下一篇文章中,我们将讨论 Theano。Theano 是一个 Python 库和优化编译器,用于计算数学表达式。

概率论入门

现在是概率论出场的时候了,它是人工智能和机器学习的另一个重要话题。对概率论的详细讨论超出了本系列的范围。我强烈建议在继续阅读之前,先通过维基百科上关于“概率”、“贝叶斯定理”和“标准差”的文章了解一些重要的术语和概念,如概率、独立事件、互斥事件、条件概率、贝叶斯定理、均值、标准差等。学习完这些后,你将能够轻松理解后面关于概率的讨论。

我们从概率分布开始讲起。根据维基百科的说法,“概率分布是一个数学函数,它能给出一个实验中不同的可能结果发生的概率”。现在,让我们试着理解什么是概率分布函数。最著名的概率分布函数是正态分布,通常也称为高斯分布(以伟大的数学家高斯的名字命名)。正态分布函数的图像是一条钟形曲线。图 6 是一个钟形曲线的例子。钟形曲线的确切形状取决于均值和标准差。让我们试着通过分析一种自然现象来理解钟形曲线。从网上可以查到,中国男性的平均身高约为1.7米。在我们周围的到多数男性的身高都非常接近这个数字。你看到一个身高低于1.4米或高于2米的男人的可能性很小。如果记录 100 万人的身高,然后以横轴为身高,纵轴为该身高的人数,绘制统计结果,你会发现绘制出的图像近似为钟形曲线,其中只有一些轻微的倾斜和弯曲。因此,正态分布很容易地捕捉到自然现象的概率特征。

图 6:钟形曲线(图像来源:维基百科)

现在,我们来看一个使用正态分布的例子。图 7 的代码中我们使用 NumPy 的正态分布的函数 normal(),然后使用 Matplotlib 进行绘图。从第 3 行我们可以看到样本大小为 1000。第 4 行绘制一个包含 1000 个 bin 的直方图。但是图 7 的钟形曲线与图 6 中看到的钟形曲线相差很大。究其原因是我们的样本数量只有 1000。样本量应该足够大才能获得更清晰的图像。将第 3 行代码替换为 sample = normal(size=100000000),行并再次执行程序。图 8 显示了一条更好的钟形曲线。这一次,我们的样本大小为 100,000,000,钟形曲线与图 6 所示非常相似。正态分布和钟形曲线只是开始。在下一篇文章中,我们将讨论可以概括其他事件和自然现象的概率分布函数。下一次,我们还将更正式地讨论这个主题。

图 7:绘制钟形曲线

本篇的内容就到此结束了。在下一篇文章中,我们将继续探索概率和统计中的一些概念。我们还将安装和使用 Anaconda,这是一个用于科学计算的 Python 发行版,对于开发人工智能、机器学习和数据科学程序特别有用。如前所述,我们还将熟悉另一个名为 Theano 的 Python 库,它在人工智能和机器学习领域被大量使用。

图 8:更好的钟形曲线

(题图:DA/2a8d805a-01d3-4039-b96c-74766491e264)


via: https://www.opensourceforu.com/2023/01/ai-an-introduction-to-probability/

作者:Deepu Benson 选题:lujun9972 译者:toknow-gh 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

网络应用防火墙(WAF)是一种在应用层监控网络流量的应用程序。

OSI(开放系统互联) 是最常被网络相关讨论引用的网络流量框架之一。当数据包通过第 6 层(表示层)移动到第 7 层(应用层)时,它会进行解密或解码操作。这些操作可能会因异常解码和解释而产生漏洞,而这些漏洞可能被利用来打破标准应用上下文。注入就是这种漏洞的一种类型,而且因为传统的 IDS/IPS 设备无法应对这些威胁,所以其长时间以来一直是人们特别关注的问题。

ModSecurity 简介

ModSecurity 本质上就是 网络应用防火墙 web application firewall (WAF)引擎。它与 Apache、IIS 和 Nginx 兼容,并由第三方公司维护。该防火墙会将一份规则列表与由 Web 服务器/代理提供的 HTTP 头流进行交叉引用。目前这个仓库已经被简化,只包含主要的 LibModSecurity 库。你可以直接在自己的服务器实现中调用这个库,或通过特定编程语言的封装进行调用。

其母公司的支持计划于 2024 年 7 月 1 日结束,之后这个项目将由开源社区维护。

安装 Nginx 连接器

Nginx 连接器 是一个 Nginx 动态模块,可以通过 Fedora 包 nginx-mod-modsecurity 进行安装。它依赖于 libmodsecurity.so,所以在这个使用场景中,这个包本身就是防火墙。

[user@fedora ~]$ sudo dnf install -y nginx nginx-mod-modsecurity
[user@fedora ~]$ rpm -qR nginx-mod-modsecurity
config(nginx-mod-modsecurity) = 1.0.3-3.fc38
libc.so.6(GLIBC_2.4)(64bit)
libmodsecurity.so.3()(64bit)
nginx(abi) = 1.24.0
nginx-filesystem
...

安装完成后,你会见到连接器在 /etc/nginx 中添加了一些重要的文件。

[user@fedora ~]$ rpm -ql nginx-mod-modsecurity
/etc/nginx/modsecurity.conf                   # waf 配置
/etc/nginx/nginx.conf.modsecurity             # nginx 示例配置
/usr/lib64/nginx/modules/ngx_http_modsecurity_module.so
/usr/share/nginx/modules/mod-modsecurity.conf
/usr/share/doc/nginx-mod-modsecurity/README.md
...

通过提供一些额外的配置指令,连接器对 Nginx 进行了扩展。下面的部分将演示 nginx.conf.modsecurity 文件中一些示例指令。指令的完整列表可以在 README.md 文件或项目的 GitHub 页面找到。

启动网络应用防火墙

nginx.conf.modsecurity 是我们将要运行的 Nginx 配置。解开如下所示的 modsecurity 行注释:

[user@fedora ~]$ sudo sed -i 's/#modsec/modsec/g' /etc/nginx/nginx.conf.modsecurity
[user@fedora ~]$ grep -C2 modsecurity /etc/nginx/nginx.conf.modsecurity
        # 如有需要,启用 ModSecurity WAF
        modsecurity on;
        # 如有需要,加载 ModSecurity CRS
        modsecurity_rules_file /etc/nginx/modsecurity.conf;

在 shell 中启动服务器并查看日志,确保在 modsecurity.conf 加载了七个默认规则。

[user@fedora ~]$ sudo nginx -c /etc/nginx/nginx.conf.modsecurity
[user@fedora ~]$ head /var/log/nginx/error.log
2023/10/21 23:55:09 [notice] 46218#46218: ModSecurity-nginx v1.0.3 (rules loaded inline/local/remote: 0/7/0)
2023/10/21 23:55:09 [notice] 46218#46218: using the "epoll" event method
2023/10/21 23:55:09 [notice] 46218#46218: nginx/1.24.0
2023/10/21 23:55:09 [notice] 46218#46218: OS: Linux 6.5.7-200.fc38.x86_64

通过发送一些不符合 Content-Type 头格式的数据来测试默认规则。

[user@fedora ~]$ curl -X POST http://localhost -H "Content-Type: application/json" --data "<xml></xml>"
[user@fedora ~]$ tail /var/log/modsec_audit.log
...
---rH5bFain---H--
ModSecurity: Warning. Matched "Operator `Eq' with parameter `0' against variable `REQBODY_ERROR' (Value: `1' ) [file "/etc/nginx/modsecurity.conf"] [line "75"] [id "200002"] [rev ""] [msg "Failed to parse request body."] [data "JSON parsing error: lexical error: invalid char in json text.\n"] [severity "2"] [ver ""] [maturity "0"] [accuracy "0"] [hostname "10.0.2.100"] [uri "/"] [unique_id "169795900388.487044"] [ref "v121,1"]

用 OWASP 核心规则集扩展你的网络应用防火墙

默认的 Nginx 连接器带有七条规则。OWASP Core Rule Set v3.3.5 则更为详尽,涵盖了许多场景。

复制并提取规则的存档。

[user@fedora ~]$ curl -fSL https://github.com/coreruleset/coreruleset/archive/refs/tags/v3.3.5.tar.gz --output /tmp/v3.3.5.tar.gz
[user@fedora ~]$ sudo tar -C /etc/nginx -xvf /tmp/v3.3.5.tar.gz
[user@fedora ~]$ tree -L 1 /etc/nginx/
/etc/nginx/
├── conf.d
├── default.d
├── modsecurity.conf          # waf 配置
├── nginx.conf
├── nginx.conf.modsecurity    # nginx 启用 waf
├── coreruleset-3.3.5
├   ├── rules                 # 规则目录
├       ...
├   ...

现在,你在 Nginx 配置文件夹中有了一个包含所有当前 OWASP 规则的 rules 目录。接下来,让 Nginx 知道这些规则。以下操作指南来源于 OWASP INSTALL 文件。

创建一个 crs.conf 文件,并在全局网络应用防火墙配置文件( modsecurity.conf )中包含所有相关的配置文件。

[user@fedora ~]$ sudo cp /etc/nginx/coreruleset-3.3.5/crs-setup.conf.example /etc/nginx/coreruleset-3.3.5/crs.conf
[user@fedora ~]$ echo -e "\nInclude /etc/nginx/coreruleset-3.3.5/crs.conf"  | sudo tee -a /etc/nginx/modsecurity.conf
[user@fedora ~]$ echo -e "\nInclude /etc/nginx/coreruleset-3.3.5/rules/*.conf" | sudo tee -a /etc/nginx/modsecurity.conf
[user@fedora ~]$ tail /etc/nginx/modsecurity.conf
Include /etc/nginx/coreruleset-3.3.5/crs.conf
Include /etc/nginx/coreruleset-3.3.5/rules/*.conf

根据文档,包含这些文件的顺序很重要。上面的 tee 的命令将新的 Include 行放在了 modsecurity.conf 文件的末尾。现在,用这个新配置重启 Nginx。

[user@fedora ~]$ sudo nginx -s stop && sudo nginx -c /etc/nginx/nginx.conf.modsecurity
[user@fedora ~]$ tail /var/log/nginx/error.log
2023/10/22 10:53:23 [notice] 202#202: exit
2023/10/22 10:53:50 [notice] 230#230: ModSecurity-nginx v1.0.3 (rules loaded inline/local/remote: 0/921/0)
2023/10/22 10:53:50 [notice] 230#230: using the "epoll" event method
2023/10/22 10:53:50 [notice] 230#230: nginx/1.24.0
2023/10/22 10:53:50 [notice] 230#230: OS: Linux 6.5.7-200.fc38.x86_64
2023/10/22 10:53:50 [notice] 230#230: getrlimit(RLIMIT_NOFILE): 524288:524288
2023/10/22 10:53:50 [notice] 231#231: start worker processes

注意,Nginx 成功加载了 921 条规则。还需要做一些测试来确保规则实际上是被网络应用防火墙检查过的。这里再次引用 INSTALL 文件中的 “Testing the Installation” 片段。

[user@fedora ~]$ curl 'http://localhost/?param=''><script>alert(1);</script>'
[user@fedora ~]$ tail /var/log/modsec_audit.log
...
---8NSpdnLe---H--
ModSecurity: Warning. detected XSS using libinjection. [file "/etc/nginx/coreruleset-3.3.5/rules/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "38"] [id "941100"] [rev ""] [msg "XSS Attack Detected via libinjection"] [data "Matched Data: XSS data found within ARGS:param: ><script>alert(1);</script>"] [severity "2"] [ver "OWASP_CRS/3.3.5"]
...

结论

本文演示了如何为 Nginx 服务器配置网络应用防火墙。这个部署使用了标准规则和 OWASP Core Rule Set v3.3.5。演示的防火墙在检测模式中运行并记录不寻常的行为。将防火墙运行在防御模式要对 modsecurity.conf 进行更多改动。请参考 ModSecurity Reference Manual v3.x) 获取如何启用防御模式和更多信息。

祝你好运。

(题图:DA/7ec85bc4-b209-4fc6-9275-8f7d1430f6ca)


via: https://fedoramagazine.org/a-web-application-firewall-for-nginx/

作者:Roman Gherta 选题:lujun9972 译者:ChatGPT 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

2011 年 3 月,苹果公司提出 RFC 6186,描述了如何利用域名系统服务(DNS SRV)记录来查找电子邮件的提交以及访问服务。现在 Postfix 从 3.8.0 版本开始支持 RFC 中提出的设计。这个新增功能让你可以使用 DNS SRV 记录进行负载分配和自动配置。

DNS SRV 记录的形态

DNS SRV 记录定义在 RFC 2782 中,它指定在区域文件中,并且包含了服务名称、传输协议规范、优先级、权重、端口,以及提供该服务的主机。

_submission._tcp    SRV 5 10 50 bruce.my-domain.com.
字段意义
服务名称submission服务名为 submission
传输协议规范tcp本服务使用 TCP 协议
优先级5服务器优先级设为 5(数值越小,优先级越高)
权重10服务器应承担的负载部分
端口50服务器监听连接的端口
目标bruce.my-domain.com.提供此服务的服务器名称

记录解释

服务器选择算法

客户端应该按照 RFC 2782 中描述的方式解析 SRV 记录。这意味着,首先尝试联系拥有最高优先级(最小的优先级数字)的服务器。如果该服务器无回应,那么重试联系拥有同样或者更低优先级的下一台服务器。当有多台服务器拥有同样优先级的时候,应随机选择其中一台,但是必须确保选择记录的概率符合下列公式:

其中 i 是 SRV 记录的标识,k 是具有相同优先级的 SRV 记录的数量。

在现实中,这意味着如果你有两台服务器,其中一台的处理能力是另一台的三倍,那么你应该给第一台服务器的权重赋于另一台三倍的值。这样就能保证更强大的服务器会接收到大约 75% 的客户端请求,而另一台接收大约 25% 的请求。

这些原则使得 SRV 记录能够同时作为客户端自动配置及在服务器之间分配工作负载的工具。

看看以下这个记录的例子:

_submission._tcp     SRV 0 0 2525 server-one
_submission._tcp     SRV 1 75 2625 server-two
_submission._tcp     SRV 1 25 2625 server-three

这里 server-one 总是会被首选来进行联系。如果 server-one 无回应,客户端就会将剩下优先级为 1 的两个记录顺序打乱,生成一个从 0 到 100 的随机数,如果第一条记录的运行总和大于或者等于这个随机数,它就会尝试去联系这个记录。否则,客户端会倒序联系所有服务器。注意,客户端会向它优先成功连接的服务器发送请求。

示例配置

请考虑以下这种情况。你想为大量的电脑配置 Postfix,使其通过公司的邮件服务器利用 SRV 记录转发外部电邮。为了达到这个目标,你需要在每台电脑的 Postfix 中配置 relayhost 参数,即邮件用户代理(MUA)。如果将 relayhost 参数的值设置为 $mydomain,你的机器将开始为你的域名查找 MX 记录,并尝试按照它们的优先级顺序发送邮件。这种方法虽然有效,但是可能会遇到负载平衡问题。Postfix 会使用优先级最高的服务器,直到其变为无响应才会联系其他备用服务器。此外,如果你在环境中使用了动态分配的端口,你无法指明哪个端口正在被特定的服务器使用。使用 SRV 记录,你可以应对这些挑战,并在需要改变服务器端口的时候维持服务器的平滑运行。

区域文件

为了使得 DNS 服务器提供信息给客户端,可以参考以下使用服务器 server-oneserver-twoserver-three 作为中继,并把服务器 server-four 配置为接收测试邮件的区域文件示例。

$TTL  3600
@       IN SOA  example-domain.com. root.example-domain.com. (
                1571655122 ; 区域文件的序列号
                1200       ; 刷新时间
                180        ; 发生问题时的重试时间
                1209600    ; 过期时间
                10800 )    ; 查询失败时的最大缓存时间
;
        IN NS   ns1
        IN A    192.168.2.0
;
ns1     IN A    192.168.2.2
server-one           IN A   192.168.2.4
server-two           IN A   192.168.2.5
server-three         IN A   192.168.2.6
server-four          IN A   192.168.2.7
_submission._tcp     SRV 0 0 2525  server-one
_submission._tcp     SRV 1 50 2625 server-two
_submission._tcp     SRV 1 50 2625 server-three
@ MX 0 server-four

Postfix MUA 配置

设置客户端机器去查找 SRV 记录:

use_srv_lookup = submission
relayhost = example-domain.com:submission

通过这个配置,你的客户端机器上的 Postfix 实例会联络到 example-domain 的 DNS 服务器,然后获取邮件提交的 SRV 记录。在这个例子中,server-one 有最高的优先级,Postfix 会先试图连接它。然后,Postfix 随机的选择剩下的两个服务器其中一个去尝试连接。这个配置确保了大约有 50% 的机会会优先联系到服务器一。注意,SRV 记录的权重值并不等同于百分比。你也可以用 1 和 1 这样的值达到同样的目标。

同时,Postfix 也知道 server-one 在监听 2525 端口,而 server-two 在监听 2625 端口。如果你正在缓存检索到的 DNS 记录,并且你动态改变 SRV 记录,那么设置一个低的生存时间(TTL)对你的记录是很重要的。

整套设置

你可以通过下面的方式尝试这个配置,包含 podman 和在此处提供的 compose 文件:

$ git clone https://github.com/TomasKorbar/srv_article
$ cd srv_article/environment
$ podman-compose up
$ podman exec -it article_client /bin/bash
root@client # ./senddummy.sh
root@client # exit

完成配置之后,你可以检查日志,查看邮件是否经过 server-one 并最终投递到 server-four

$ podman stop article_server1
$ podman exec -it article_client /bin/bash
root@client # ./senddummy.sh
root@client # ./senddummy.sh
root@client # ./senddummy.sh
root@client # ./senddummy.sh
root@client # ./senddummy.sh
root@client # ./senddummy.sh
root@client # exit

现在 server-one 已经关闭了,这六封邮件将会由 server-two 或者 server-three 中转发出去。

仔细看一下 Dockerfiles 以更深地理解这个配置。

通过执行:$ podman-compose down 完成示例的操作。

(题图:DA/241079fe-58d6-4dc6-8801-f0fd19dfd64b)


via: https://fedoramagazine.org/using-postfix-dns-srv-record-resolution-feature/

作者:Tomáš Korbař 选题:lujun9972 译者:ChatGPT 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

用这些技巧释放 sudo 的力量 ?

你应该熟悉 sudo 吧?肯定有过使用的经验。

对多数 Linux 用户来说,sudo 就像一个神器,赋予了他们作为 root 用户执行任意命令或切换到 root 用户身份的能力。

其实这只掌握了一半的真相。sudo 绝非仅仅只是一条命令,sudo 是一款你可以根据需求和偏好去定制的工具

Ubuntu、Debian 以及其他的发行版在默认的配置下,赋予了 sudo 以 root 用户的身份执行任意命令的权限。这让很多用户误以为 sudo 就像一个魔法开关,瞬间可以获取到 root 权限。

比如说,系统管理员可以设置成只有属于特定的 dev 组的部分用户才能用 sudo 来执行 nginx 命令。这些用户将无法用 sudo 执行任何其他命令或切换到 root 用户。

如果你对此感到惊讶,那很可能是你一直在使用 sudo,但对其底层的工作原理并没有太多了解。

在这个教程中,我并不会解释 sudo 是如何运作的,这个主题我会在另一天讲解。

在这篇文章中,你将看到 sudo 的不同特性可以如何被调试和改进。有些可能真的很有用,有些可能完全没什么帮助,但是挺有趣。

? 请不要随意去尝试所有提到的改进。如果处理不慎,你可能会遭遇无法运行 sudo 的混乱状态。在大多数情况下,平静阅读并知道这些就好。如果你决定尝试一些改进步骤,请先备份你的系统设置,这样在需要的时候能把事情恢复到正常。

1、编辑 sudo 配置时,请始终使用 visudo

sudo 命令是通过 /etc/sudoers 文件进行配置的。

虽然你可以用你最喜欢的 终端文本编辑器 编辑这个文件,比如 Micro、NeoVim 等,但你千万不要这么做。

为什么这么说呢?因为该文件中的任何语法错误都会让你的系统出问题,导致 sudo 无法工作。这可能会使得你的 Linux 系统无法正常使用。

你只需要这样使用即可:

sudo visudo

传统上,visudo 命令会在 Vi 编辑器中打开 /etc/sudoers 文件。如果你用的是 Ubuntu,那么会在 Nano 中打开。

这么做的好处在于,visudo 会在你试图保存更改时执行语法检查。这能确保你不会因为语法错误而误改 sudo 配置。

visudo 在保存到 sudoers 文件的变更前检查语法

好了!现在你可以看看 sudo 配置的一些改变。

? 我建议你备份 /etc/sudoers 文件(sudo cp /etc/sudoers /etc/sudoers.bak)。这样,如果你不确定你做了哪些更改,或者你想恢复到默认的 sudo 配置,那你可以从备份文件中复制。

2、输入 sudo 密码时显示星号

我们的这种输入行为是从 UNIX 系统中继承下来的。当你在终端输入 sudo 密码时,屏幕上不会有任何显示。这种缺乏反馈的现象,往往让新的 Linux 用户怀疑自己的系统已经卡住了。

人们常说,这是一项安全功能。或许在上个世纪是这样,但我个人觉得我们没有必要继续这样下去。

不过,一些发行版,如 Linux Mint,已经对 sudo 进行了优化,当你输入密码时会显示星号。

这样的方式更符合我们的日常经验。

如果想让 sudo 输入密码时显示星号,运行 sudo visudo 并找到以下行:

Defaults env_reset

然后将其更改为:

Defaults env_reset,pwfeedback

? 在某些发行版中,比如 Arch,你可能找不到 Defaults env_reset 这一行。如果这样的话,只需新增一行 Defaults env_reset, pwfeedback 就可以了。

现在,当 sudo 需要你输入密码时,你会看到输入的密码变成了星号。

✋ 如果你注意到即使密码正确也无法通过一些图形化应用,如软件中心,那就该撤销这项更改。一些较旧的论坛帖子曾提到过此类问题,虽然我自己还未遇到过。

3、增加 sudo 密码超时时限

当你首次使用 sudo 时,它会要求输入密码。但在随后相当一段时间里,你使用 sudo 执行命令就无需再次输入密码。

我们将这个时间间隔称为 sudo 密码超时 (暂且称为 SPT,这是我刚刚编的说法,请不要真的这样称呼 ?)。

不同的发行版有不同的超时时间。可能是 5 分钟,也可能是 15 分钟。

你可以根据自己的喜好来改变这个设置,设定一个新的 sudo 密码超时时限。

像你之前看到的,编辑 sudoers 文件,找到含有 Defaults env_reset 的行,并在此行添加 timestamp_timeout=XX,使其变成如下形式:

Defaults        env_reset, timestamp_timeout=XX

其中 XX 是以分钟为单位的超时时长。

如果你还有其他参数,例如你在上一节中看到的星号反馈,它们都可以在一行中组合起来:

Defaults        env_reset, timestamp_timeout=XX, pwfeedback
? 同样地,你还可以控制密码重试的次数上限。使用 passwd_tries=N 来修改用户可以输入错误密码的次数。

4、在不输入密码的情况下使用 sudo

行!你已经增加了 sudo 密码超时时限(或者称之为 SPT。哇塞!你还在坚持这个叫法 ?)。

这样很好。我的意思是,毕竟没人愿意每几分钟就输入一次密码。

扩大超时时限是一方面,另一方面则是尽可能不去使用它。

是的,你没听错。你就是可以在无需输入密码的情况下使用 sudo

从安全角度来看,这听起来似乎很冒险,对吧?的确如此,但在某些实际情况下,你确实会更青睐无密码的 sudo

例如,如果你需要远程管理多台 Linux 服务器,并为了避免总是使用 root,你在这些服务器上创建了一些 sudo 用户。辛酸的是,你会有太多的密码。而你又不想对所有的服务器使用同一的 sudo 密码。

在这种情况下,你可以仅设置基于密钥的 SSH 访问方式,并允许使用无需密码的 sudo。这样,只有获得授权的用户才能访问远程服务器,也不用再记住 sudo 密码。

我在 DigitalOcean 上部署的测试服务器上就采用了这种方法,用来测试开源工具和服务。

好处是这可以按用户进行设置。使用以下命令打开 /etc/sudoers 文件进行编辑:

sudo visudo

然后添加如下行:

user_name ALL=(ALL) NOPASSWD:ALL

当然,你需要将上面行中的 user_name 替换为实际的用户名。

保存文件后,你就可以享受无密码的 sudo 生活了。

5、配置独立的 sudo 日志文件

查阅 syslog 或 journal 日志,我们可以找到关于 sudo 的所有条目,但若需要单独针对 sudo 的记录,可以专门创建一个自定义的日志文件。例如,选择 /var/sudo.log 文件来存储日志。这个新的日志文件无需手动创建,如果不存在,系统会自动生成。

编辑 /etc/sudoers 文件,采用 visudo 命令,并在其中添加以下内容:

Defaults  logfile="/var/log/sudo.log"

保存该文件后,便可以在其中查看哪些命令在何时、由哪位用户通过 sudo 运行了。

6、限制特定用户组使用 sudo 执行特定命令

这是一种高级解决方案,系统管理员在需要跨部门共享服务器的多用户环境中会使用。

开发者可能会需要以 root 权限运行 Web 服务器或其他程序,但全权给予他们 sudo 权限会带来安全风险。我建议在群组级别进行此项操作。例如,创建命名为 coders 的群组,并允许它们运行在 /var/www/opt/bin/coders 目录下的命令(或可执行文件),以及 inxi 命令(路径是 /usr/bin/inxi 的二进制文件)。这是一个假想情景,实际操作请谨慎对待。

接下来,用 sudo visudo 编辑 sudoer 文件,再添加以下行:

%coders   ALL=(ALL:ALL) /var/www,/opt/bin/coders,/usr/bin/inxi

如有需要,可以添加 NOPASSWD 参数,这样允许使用 sudo 运行的命令就不再需要密码了。

关于 ALL=(ALL:ALL) 的详细解读,我们将会在其他文章中进行讲解,毕竟这篇文章已经解释的内容足够多了。

7、检查用户的 sudo 权限

好吧,这是个小提示,而不是系统调优技巧。

如何确认一个用户是否具有 sudo 权限呢?可能有人会说,查看他们是否是 sudo 组的成员。但这并不一定准确,因为有些发行版用的是 wheel 代替 sudo 分组。

更佳的方法是利用 sudo 内建的功能,看看用户具有哪种 sudo 权限:

sudo -l -U user_name

这将显示出用户具有执行部分命令或所有命令的 sudo 权限。

如你所见,我拥有自定义日志文件、密码反馈以及执行所有命令的 sudo 权限。

如果一个用户完全没有 sudo 权限,你将看到如下提示:

User prakash is not allowed to run sudo on this-that-server.

? 附加内容:输错 sudo 密码时,让系统“侮辱”你

这是个我在文章开头提到的“无用”小调整。

我想你在使用 sudo 时肯定曾误输过密码,对吧?

这个小技巧就是,在你每次输错密码时,让 sudo 抛出随机的“侮辱”

sudo visudo 修改 sudo 配置文件,然后添加以下行:

Defaults   insults

修改后,你可以故意输错密码,测试新的设置。

你可能在想,谁会喜欢被侮辱呢?只有粉丝可以以直白的方式告诉你 ?

你是如何运用 sudo 的?

我知道定制化的可能性无穷无尽,但其实,一般的 Linux 用户并不会去自定义 sudo

尽管如此,我还是热衷于与你分享这些因为你可能会发现一些新奇且实用的东西。

? 那么,你有发现什么新的东西吗?请在评论区告诉我。你有一些秘密的 sudo 技巧欢迎和大家分享!

(题图:DA/a12900e5-e197-455e-adfc-0b52e4305b91)


via: https://itsfoss.com/sudo-tips/

作者:Abhishek Prakash 选题:lujun9972 译者:ChatGPT 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出