5 个版本 (3 个主要版本)

4.0.0 2024 年 8 月 23 日
3.0.0 2024 年 7 月 30 日
2.0.0 2024 年 7 月 18 日
1.1.0 2024 年 7 月 7 日
0.0.0 2024 年 7 月 1 日

#920网络编程

Download history 252/week @ 2024-06-28 132/week @ 2024-07-05 75/week @ 2024-07-12 71/week @ 2024-07-19 143/week @ 2024-07-26 13/week @ 2024-08-02

每月 289 次下载

MIT/Apache

120KB
2K SLoC

letmein - 认证端口敲击

Letmein 是一个具有简单且安全的认证机制的简单端口敲击工具。它可以用来加强 SSH、VPN、IMAP 等服务对预认证攻击的防御。

Letmein 将服务隐藏在服务器后的敲击认证屏障后面,以减少服务的攻击面。除非敲击认证成功,否则服务将不可访问。在敲击成功的情况下,letmeind 服务器只为执行敲击的客户端 IP 地址打开被敲击的端口。具有不同 IP 地址的机器仍然无法访问受保护的服务。

无法成功认证敲击序列的机器无法访问受保护的服务。它们将在受保护服务的端口上收到 TCP/ICMP reject,并提供了 nftables.conf 的示例。(您也可以选择在您的 nftables.confdrop 数据包)。

Letmein 需要 nftables 基于的防火墙。它不与 iptables 一起工作。如果您使用基于 iptables 的防火墙,请在安装 letmein 之前将其转换为 nftables。有关如何做到这一点,互联网上有描述。这并不像听起来那么困难或耗时。 :)

典型的 letmein 操作流程

image

主页

Git 仓库

Github 仓库

使用示例:将 OpenSSH (sshd) 访问放在敲击认证屏障后面

在服务器上安装 letmein 服务器软件(见以下章节)。

在客户端安装 letmein 客户端软件(见下文各节)。

请阅读本项目提供的示例配置文件 nftables.conf。需要在现有的 nftables 配置中添加一个 letmein 特定的输入链。相应地修改您的 nftables.conf 文件。

使用以下客户端命令生成共享密钥和用户标识符,以安装在服务器和客户端上

letmein gen-key -u 00000000

gen-key 命令将生成的密钥字符串打印到控制台。默认情况下,这将为用户标识符 00000000 生成一个安全的随机密钥。您可以手动编辑用户标识符,如果需要的话,或者您可以保持原样。

将生成的字符串(用户标识符和共享密钥)添加到 /opt/letmein/etc/letmeind.conf 中的服务器配置中。将生成的密钥字符串与用户标识符一起放入配置文件的 [KEYS] 部分。

将相同的生成字符串(用户标识符和共享密钥)添加到 /opt/letmein/etc/letmein.conf 中的客户端配置中。将生成的密钥字符串与用户标识符一起放入配置文件的 [KEYS] 部分。

在服务器中创建一个 resource,描述可以打开的 sshd 端口。在服务器配置文件 /opt/letmein/etc/letmeind.conf[RESOURCES] 部分,必须指定所有可能打开的端口。一个资源由一个资源标识符后跟一个端口标识符组成,如下所示

[RESOURCES]
00000022 = port: 22

资源标识符是一个 8 位十六进制数。在此示例中为 22(hex),但它可以是任何数字。它只需要在服务器和客户端上是相同的数字。在 port: 之后指定可以敲开的端口号(十进制)。

将相同的资源以及相同的资源标识符和端口号添加到 /opt/letmein/etc/letmein.conf 中的客户端配置中。

重启 letmein 服务器

systemctl restart letmeind.service

现在从您的防火墙配置中的静态 sshd 端口(22) accept 中删除。letmein 将在成功敲击认证后动态地将此类规则安装到 letmein 输入链中。然后重启 nftables

systemctl restart nftables.service

完成!现在您应该能够敲开服务器上的 sshd 端口

# This must fail! No successful knock authentication, yet.
# If this does not fail, check if you have removed the sshd accept rule from nftables.conf.
ssh your-server.com

# Knock-open port 22 (sshd) on the server using user-id/key 00000000:
# (You do not have to specify -u 00000000 if that is your default user (see config).)
letmein knock -u 00000000 your-server.com 22

# Now you should be able to ssh into your server successfully:
ssh your-server.com

要在连接 ssh 之前自动敲击端口,您可以在 ~/.ssh/config 文件中添加一个 Match exec 规则

Match host your-server.com exec "letmein knock -u 00000000 your-server.com 22"

先决条件

必须安装 Rust 编译器来构建 letmein。建议使用最新版本的稳定 Rust 编译器

Rust 安装程序

Rust 安装程序将安装编译器和构建工具 cargo

构建需要安装额外的 cargo-auditcargo-auditable 工具。运行以下命令安装这两个工具

cargo install cargo-audit cargo-auditable

在运行时,nftables 的 nft 二进制文件必须已安装并可在 $PATH 中访问。在 Debian 上,请安装 nftables 软件包

apt install nftables

构建 letmein

运行 build.sh 脚本以构建 letmein。

安装所有构建必备条件后,运行构建脚本

./build.sh

安装 letmein

安装客户端

然后运行 install-client.sh 来安装 letmein 客户端到 /opt/letmein/

./install-client.sh

客户端用于向服务器发送敲击数据包。

安装服务器

为服务器准备用户和组

letmein 服务器面向公共网络的部分以较低权限运行,以减少攻击面。

为了使其工作,用户 letmeind 和组 letmeind 必须存在于 /etc/passwd/etc/group 中。建议此用户没有分配shell和家目录,因此不是登录用户。

您可以使用以下辅助脚本在您的系统中创建用户和组

./create-user.sh

安装服务器和 systemd 单元

在构建并创建 letmeind 系统用户后,运行 install-server.sh 将 letmeind 服务器安装到 /opt/letmein/

./install-server.sh

安装服务器还会将服务和一个套接字安装到 systemd 并启动 letmeind 服务器。

服务器用于接收客户端的敲击数据包。在敲击认证成功后,服务器将在其 nftables 防火墙中打开敲击端口。

平台支持

客户端

客户端应用程序 letmein 是可移植的,应在所有主流平台上运行。已测试的平台有:

  • Linux
  • Android,在 Termux
  • Windows
  • MacOS(仅测试了构建)

服务器

服务器应用程序 letmeind 仅支持 Linux,因为它只支持 nftables 作为防火墙后端。

安全通知:用户标识符和资源标识符

请注意,配置文件中的用户标识符和资源标识符以明文形式在网络中传输,未加密。

确保用户标识符和资源标识符不包含任何私人信息。

这些标识符仅用于为不同的 letmein 密钥、安装和配置提供抽象标识。

内部结构和设计目标

letmein 的主要设计目标是:

  • 它使用一种内存安全的编程语言实现,这使得某些严重错误类别的错误成为不可能。
  • 算法和实现尽可能简单。
  • 它不实现复杂的加密算法,如非对称的公钥/私钥加密。它使用共享密钥和 HMAC/SHA3 进行身份验证。
  • 它具有重放保护。重放敲击数据包序列不会导致成功认证。
  • 它只为发起敲击请求的 IP 地址打开端口。默认情况下,对于 IPv4 和 IPv6,如果可用。此行为可以通过客户端命令行选项 -4-6 进行调整。
  • letmein 不链接到用不安全语言编写的库 (.so),除非是操作系统或 Rust 编译器要求的。唯一的动态链接库是:
    • libc.so
    • libm.so
    • libgcc_s.so
    • linux-vdso.so
    • ld-linux-*.so
    • ld-android.so(仅限 Android)
    • libdl.so(仅限 Android)
    • libarmmem-*.so(仅限树莓派)

安全分析

据我所知,该程序已被精心设计以具有安全性。

然而,没有人是不犯错的。

  • 请阅读代码并对它进行评论。
  • 如有疑问、建议或请求,请随时提交问题。
  • 请讨论设计决策的优缺点。

我很想听听您的意见。

如果您发现了一个安全漏洞,请参阅漏洞报告流程了解如何操作。

已知弱点

letmein存在一些已知的弱点。在本段中,我们将讨论这些弱点存在的原因。

这些弱点并未被letmein的设计考虑在内以简化设计。这是简单设计与实际影响安全的弱点之间的权衡。

人们认为,这些弱点不会使letmein在实际使用中不安全。简单的目的是减少攻击面,从而提高安全性。

  • 弱点:用户标识符和资源标识符从配置中以明文形式在网络中传输。

    • 理由:用户标识符和资源标识符不应包含私有或机密信息。
  • 弱点:第一个Knock数据包没有防范重放攻击。

    • 理由:确实,攻击者可以成功重放Knock数据包。但这并不重要。攻击者仍然无法成功解决Challenge。由于在给定的设计中易于实现,并且它阻止了没有密钥的端口敲击,因此仅实现了Knock的认证。
  • 弱点:在合法用户成功敲击序列之后,如果攻击者能够使用与合法用户相同的发送IP地址,则可以使用打开的端口。

    • 理由:letmein仅认证敲击序列期间发生的事情。一旦为IP地址打开了防火墙,敲击序列之后发生的事情完全超出letmein的范畴。然而,敲击序列成功后,端口保持打开的时间有限。敲击序列完成后,中间人攻击者可以使用的仅限于有限的时间。
  • 弱点:如果您在NAT后面打开端口,则该端口将为整个NAT网络打开,因为从外部看,NAT网络只有一个IP地址。NAT网络内的每个人都能访问打开的端口。

    • 理由:端口仅短暂且有限地打开,并假设存在第二层安全(见下面的双因素认证讨论)。虽然端口为整个NAT网络打开是不幸的事实,但这仍然比(没有端口敲击器)整个互联网打开要好得多。
  • 弱点:认证密钥是一个共享的秘密,它以明文形式存储在服务器和客户端上。

    • 原因:确实,能够成功控制服务器或客户端的攻击者可以窃取密钥并验证未来的会话。这是在实现复杂的公私钥加密(letmein旨在保护的整体目标)与设计简单性之间的一种权衡。letmein 应该保护其他未受保护的服务。它只应该在已经安全系统中作为 额外的 安全屏障。将其视为 2FA。如果攻击者能够获取letmein密钥,有两种情况:要么存在第二个安全屏障(例如,ssh服务器登录),要么无论如何都会失去一切,因为攻击者已经拥有完全访问权限。
  • 弱点:所有成功验证letmein的用户都可以开始攻击受保护的服务。

    • 原因:是的,这几乎是不可能预防的。letmein旨在防止预认证攻击。但是,可以限制用户使用某些端口。这样,用户只能使用服务器配置中明确允许的资源进行认证。
  • 弱点:线协议没有未来更改和更新的机制。

    • 原因:虽然这使更新到新协议版本变得更加困难,但它通过简化设计来提高安全性。预计未来不会有很多不兼容的协议更改。

许可证

版权(c)2024 Michael Büsch [email protected]

根据您的选择,在Apache许可证版本2.0或MIT许可证下授权。

依赖项

~5–14MB
~138K SLoC