如何使用 Vala 建立 TLS 连接?

Posted

技术标签:

【中文标题】如何使用 Vala 建立 TLS 连接?【英文标题】:How can I make a TLS connection using Vala? 【发布时间】:2021-11-18 02:44:36 【问题描述】:

我正在尝试弄清楚如何使用 Gio 建立正确的 TLS 连接。 Gio 文档说您可以通过在 SocketClient 上设置 tls 标志来创建 TLS 连接。下面是来自 gnome wiki 的 Gio 网络示例。当我设置tls 标志时,TLS 层会自动配置,但除非我跳过验证,否则验证证书会失败。

我必须自己验证证书还是应该由GLib 进行验证?有人可以提供有关如何在 Vala 中使用 TLS 的完整示例吗?

var host = "developer.gnome.org";

try 
    // Resolve hostname to IP address
    var resolver = Resolver.get_default ();
    var addresses = resolver.lookup_by_name (host, null);
    var address = addresses.nth_data (0);
    print (@"Resolved $host to $address\n");

    // Connect
    var client = new SocketClient ();
    client.set_tls(true);
    // skips certificate validation
    client.set_tls_validation_flags( 0 );

    var conn = client.connect (new InetSocketAddress (address, 443));
    print (@"Connected to $host\n");

    // Send HTTP GET request
    var message = @"GET / HTTP/1.1\r\nHost: $host\r\n\r\n";
    conn.output_stream.write (message.data);
    print ("Wrote request\n");

    // Receive response
    var response = new DataInputStream (conn.input_stream);
    var status_line = response.read_line (null).strip ();
    print ("Received status line: %s\n", status_line);

 catch (Error e) 
    stderr.printf ("%s\n", e.message);

我想问的另一件事是;当我运行上面的代码时,我得到了这个输出:

Resolved developer.gnome.org to 8.43.85.14
Connected to developer.gnome.org
Wrote request
Received status line: HTTP/1.1 200 OK

但是当我尝试连接 'developer.mozilla.org' 时,我收到以下错误:

Resolved developer.mozilla.org to 54.192.235.2
Error performing TLS handshake: A packet with illegal or unsupported version was received.

谁能告诉我出现此错误的原因? (顺便说一下我系统上安装的GLib版本是2.64.6)

【问题讨论】:

【参考方案1】:

尝试使用export G_MESSAGES_DEBUG=all 运行程序以获取完整的调试消息。

此外,有关使用 Vala 通过 GIO 编写的 TLS 的完整代码示例,请查看此 Gemini 浏览器的代码:https://github.com/koyuspace/fossil/blob/main/src/util/connection_helper.vala

希望对你有点用处。

【讨论】:

感谢您的指针和链接。我会尽快检查。【参考方案2】:

到目前为止,您所做的大部分是正确的,但您可能需要做更多的事情来处理 TLS 握手期间的潜在证书错误(见下文)。

我必须自己验证证书还是应该由 GLib 进行验证?

请注意,SocketClient.set_tls_validation_flags 已弃用。要处理验证错误,您可以在握手之前连接到 TlsClientConnection 上的 accept_certificate 信号:

var client = new SocketClient ();
client.set_tls(true);
client.event.connect ((SocketClientEvent event, SocketConnectable connectable, iostream? connection) => 
    if (event == SocketClientEvent.TLS_HANDSHAKING) 
        ((TlsClientConnection) connection).accept_certificate.connect ((peer_cert, errors) => 
            // Return true to accept, false to reject
        );
    
);

errorsGLib.TlsCertificateFlags,因此您需要确定哪些(如果有)是可接受的。理想情况下,如果有任何错误,您会完全拒绝证书,但如果您想允许例如自签名证书,则可以采用这种方式。

您可以简单地检查标志以查看 errors 中包含哪些标志:

TlsCertificateFlags[] flags = new TlsCertificateFlags[] 
    TlsCertificateFlags.BAD_IDENTITY,
    TlsCertificateFlags.EXPIRED,
    TlsCertificateFlags.GENERIC_ERROR,
    TlsCertificateFlags.INSECURE,
    TlsCertificateFlags.NOT_ACTIVATED,
    TlsCertificateFlags.REVOKED,
    TlsCertificateFlags.UNKNOWN_CA
;
foreach (var flag in flags) 
    if ((errors & flag) != 0) 
        // The flag was included in the errors - respond accordingly
    


但是当我尝试连接“developer.mozilla.org”时,我得到了 以下错误:

将 developer.mozilla.org 解决为 54.192.235.2 执行 TLS 时出错 握手:收到非法或不支持版本的数据包。

谁能告诉我出现此错误的原因? (由 我系统上安装的 GLib 版本是 2.64.6)

这可能是由于developer.mozilla.org 使用了旧的 TLS 实现(可能是 1.0 或 1.1)。根据此错误报告,自 2.64.x 起,这些在 GLib 网络中被禁用:https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=954742

自从您发布此问题后,他们可能已升级到 TLS 1.2 - 我刚刚进行了快速测试并成功使用 TLSv1.2 连接。

【讨论】:

以上是关于如何使用 Vala 建立 TLS 连接?的主要内容,如果未能解决你的问题,请参考以下文章

设置和验证 Python MySQL 连接中使用的 SSL/TLS 版本

如何使用 TLS/SSL 连接 xmpp 服务器?

如何在 Windows 上对 PHPMailer/OpenSSL TLS SMTP 进行故障排除?

如何在 IBM java 1.6 中启用 TLS 1.2?

错误:底层连接已关闭:无法为 SSL/TLS 安全通道建立信任关系

错误:客户端网络套接字在建立安全 TLS 连接之前断开