#vpn #reverse-engineering #vpn-client #openaws

app openaws-vpn-client

使用Rust编写的非官方开源AWS VPN客户端

9个版本

0.1.8 2024年3月1日
0.1.7 2023年3月21日
0.1.6 2022年12月16日
0.1.5 2022年11月29日
0.1.4 2021年12月26日

#114 in GUI

Download history

每月 202 次下载

MIT 许可证

55KB
1.5K SLoC

免责声明:这是一个Linux版本的AWS VPN客户端的非官方实现。它与AWS没有任何关系。

Open AWS VPN客户端

这是一个基于对 samm-git/aws-vpn-client 的逆向工程和研究,并在 他们的博客 中发布的非官方AWS VPN客户端。

关于实现的全部功劳归 samm-git,我们只是创建了一个用户友好的GUI,并将服务器和shell脚本重写为Rust。

此客户端仅适用于基于SAML的身份验证VPN连接。发行版已经通过 openvpn 支持常规VPN连接。

如何使用

连接

首先打开GUI,通过单击高亮区域选择您的AWS .ovpn 文件。

How to open VPN file

然后单击 连接 按钮。

How to connect

将开始常规连接流程,登录AWS账户。如果身份验证成功,您将被重定向到本地地址,该地址将加载身份验证凭据。

凭据加载后,将执行OpenVPN命令,这需要root权限,因此使用 pkexec 启动OpenVPN,它会提示您输入root密码。

断开连接

单击 断开连接 按钮或关闭GUI,将断开VPN连接,这也需要root权限(并且使用 pkexec)来终止OpenVPN进程。

如果openaws-vpn-client崩溃,VPN连接不会关闭,但在您下次打开GUI时,您将要求您终止旧的OpenVPN进程。

CTRL+C和SIGTERM不受此影响,它们始终会终止OpenVPN进程。

我很快会提供一个更好的解决方案。

安装

目前,我们没有安装脚本,但您可以从 GitLab 轻松下载工件。

构建

AWS VPN 需要一个定制的 openvpn 客户端,幸运的是(因为 OpenVPN GPL 许可证的约束),这个客户端是开源的。Alex Samorukov/samm 创建了基于该客户端源代码的补丁文件,因此我们可以轻松应用这些补丁并构建一个定制的 OpenVPN 客户端。Alex Samorukov/samm

构建自定义 OpenVPN 客户端

scripts/patch-openvpn.sh 提供了一个构建脚本,该脚本从官方 OpenVPN 网站下载 OpenVPN 源代码和来自 Alex Samorukov GitHub 的补丁文件,然后应用补丁并构建客户端,将许可证和二进制文件复制到 share/openvpn

构建 openaws-vpn-client

构建 openaws-vpn-client 需要一个夜间 rust 工具链,你可以使用 rustup 安装它,然后运行 cargo +nightly build

要求

为了构建 openaws-vpn-client,您需要在系统中安装 gtk3glibcairo,可能还需要其他库,例如 glibc,因为客户端依赖于一些 libc 函数。

目前,我们不提供基于 musl 的二进制文件,但我们有 musl/Dockerfile 的初步工作,它可以编译,但尚未启动。

我为什么开始这个项目

Amazon 已经为 Linux 提供了官方 VPN 客户端,问题是

  • 它使用 Mono,所以不是完全本地的
  • 它并非适用于所有 Linux 发行版
    • 似乎只在 .deb 发行版上工作
    • 在其他发行版上有可用的替代方案,但有时它们会损坏¹。
  • 它是闭源的,所以我不能简单地为其他发行版的问题提交 PR

我使用 Arch Linux,我尝试了官方客户端的 AUR 版本,最新版本不起作用,所以我下载了一个旧版本,它打开了但不起作用,无法连接到 VPN,出现了一个通用的错误。

所以我花了几小时寻找解决方案,最终在 samm-git/aws-vpn-client 找到了一个替代客户端,它基于 2020 年发布在 他们的博客 上的逆向工程研究。这个脚本不起作用,但它比 Arch 上的官方客户端更接近,它是开源的,易于调试、调整和测试,几个小时后,我能够让脚本工作,所以我决定基于研究和我手中的原始脚本创建一个用户友好的开源 GUI。

所以,感谢 samm-git 抽出时间进行研究并编写包装器,解决了我的问题。

混乱的代码

代码完全是用 Rust 编写的,但它处于非常混乱的状态,并且非常依赖于引用计数,没有充分利用 Rust 的所有权系统。这种方法主要因为 GTK 本身是基于引用计数的,所以以这种方式编写更容易。

此外,GTK 不是一个 Rust 框架,因此很难编写多线程 GUI 应用程序,我需要启动一个 HTTP 服务器,通常使用 Tokio 来完成,我还需要在后台启动一些进程,这最终导致需要实现 Send + Sync 的结构体,中间还有一些重构,所以有一些结构体实现了 Send + Sync 但不需要标记,其他只是有糟糕的实现。

有很多可能会引发恐慌的 unwrap() 调用,如果发生恐慌,应用程序将直接崩溃。一旦我有些时间,我将着手改进代码,但到目前为止,它已经运行正常,并解决了我的问题。因此,我发布了这个项目,这样也可以帮助到其他人。

堆栈

  • GTK3
  • Warp
  • Tokio

依赖项

~27–38MB
~696K SLoC