问题的简短版本
假设相关文件存在,为什么以下命令序列不起作用?
socat tcp-listen:10001,fork exec:'/bin/cat' &
socat openssl-listen:10002,fork,reuseaddr,cert=server.pem,cafile=client.crt tcp:localhost:10001 &
socat tcp-listen:10003 openssl-connect:localhost:10002,cert=client.pem,cafile=server.crt &
socat stdout tcp:localhost:10003
问题的长版本
我正在尝试按照以下文档所述使用socat
with :openssl
对于上下文,我在 Debian 9 上运行 socat 版本 1.7.2.4+sigfix 和 OpenSSL 版本 1.1.0f。
在继续尝试之前openssl
,我首先使用socat
它本身作为健全性检查。我启动一个socat
实例作为“回显服务器”,使用两个中间socat
实例(即第二个和第三个实例)创建隧道,然后将第四个实例作为“客户端”通过隧道将数据发送到原始进程。这是我运行的命令的示例:
socat tcp-listen:10001,fork exec:'/bin/cat' &
socat tcp-listen:10002,fork tcp:localhost:10001 &
socat tcp-listen:10003,fork tcp:localhost:10002 &
socat stdout tcp:localhost:10003
这按预期工作 - 输入到终端的文本会回显到控制台。示例会话如下所示:
user@host:~$ socat tcp-listen:10001,fork exec:'/bin/cat' &
[1] 1001
user@host:~$ socat tcp-listen:10002,fork tcp:localhost:10001 &
[2] 1002
user@host:~$ socat tcp-listen:10003,fork tcp:localhost:10002 &
[3] 1003
user@host:~$ socat stdout tcp:localhost:10003
hey
hey
验证了我的理智后,我继续进行证书和密钥生成过程。
首先,我生成了服务器密钥和自签名证书:
openssl genrsa -out server.key 2048
openssl req -new -key server.key -x509 -days 3653 -out server.crt
cat server.key server.crt > server.pem
chmod 600 server.key server.pem
然后我生成了客户端密钥和自签名证书:
openssl genrsa -out client.key 2048
openssl req -new -key client.key -x509 -days 3653 -out client.crt
cat client.key client.crt > client.pem
chmod 600 client.key client.pem
最后我尝试设置与以前相同的隧道,但使用 OpenSSL 加密:
socat tcp-listen:10001,fork exec:'/bin/cat' &
socat openssl-listen:10002,fork,reuseaddr,cert=server.pem,cafile=client.crt tcp:localhost:10001 &
socat tcp-listen:10003 openssl-connect:localhost:10002,cert=client.pem,cafile=server.crt &
socat stdout tcp:localhost:10003
这似乎不起作用,执行最后一个命令后,我收到以下错误:
YYYY/mm/dd HH:MM:SS socat[pid1] E SSL_connect(): error:14082174:SSL routines:SSL3_CHECK_CERT_AND_ALGORITHM:dh key too small
YYYY/mm/dd HH:MM:SS socat[pid2] E SSL_accept(): error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
以下是示例会话的样子:
user@host:~$ socat tcp-listen:10001,fork exec:'/bin/cat' &
[1] 1001
user@host:~$ socat openssl-listen:10002,fork,reuseaddr,cert=server.pem,cafile=client.crt tcp:localhost:10001 &
[2] 1002
user@host:~$ socat tcp-listen:10003 openssl-connect:localhost:10002,cert=client.pem,cafile=server.crt &
[3] 1003
user@host:~$ socat stdout tcp:localhost:10003
2018/08/22 23:43:30 socat[1005] E SSL_accept(): error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
2018/08/22 23:43:30 socat[1003] E SSL_connect(): error:14082174:SSL routines:SSL3_CHECK_CERT_AND_ALGORITHM:dh key too small
[3]+ Exit 1 socat tcp-listen:10003 openssl-connect:localhost:10002,cert=client.pem,cafile=server.crt
遵循用户的建议戴夫·汤普森_085我尝试使用openssl s_client
以下命令:
openssl s_client -cipher 'DHE:!EXPORT:!LOW' -connect localhost:10002
这产生了错误输出,其中包含以下内容:
socat[pid] E SSL_accept(): error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small:../ssl/statem/statem_clnt.c:1460:
答案1
首先,你确定索卡特正在使用 OpenSSL 1.1.0?上游(来自 socat.org)1.7.2.4 源(2014 年发布)与 OpenSSL 1.1.0(2016 年发布)不兼容,后者对 API 进行了重大更改。查看ldd $(which socat)
。您的 socat 和 OpenSSL(两者)是来自标准存储库、其他构建器/打包器,还是从源代码构建?
无论如何,尽管“新内容”没有这么说,并且假设“sig”补丁是什么都不会改变它,但 1.7.2.4(上游)源默认为 512 位 DH 参数。这确实太小了——甚至在 Logjam 之前就知道它是易碎的,并且对于 1.0.1n 或 1.0.2b 及以上版本(均于 2015-06 发布)的任何 libssl 客户端来说都是不可接受的(并且任何1.1.0,首次发布于 2016 年 8 月)。
AFAICS 您的选择是:
将 socat 升级到至少 1.7.3.0(上游确实有 1024 位); 3.1+ 2048 位更好
生成或从某处获取至少 1024 位的 DH 参数(对于大多数客户端(包括您的客户端)来说 2048 更好,尽管一些客户端可能会遇到问题(例如 Java 版本过时),并将它们添加到服务器的
cert
文件中。您可以使用 1024 或 2048 生成 DH
openssl dhparam $n >file
参数$n
。如果这太慢你可以添加-dsaparam
。同上,但将参数放在服务器上配置的单独文件中。联机帮助页说这个选项是,
dhparams=<file>
但代码说它是,dh=
并且测试证实了后者。配置服务器或客户端,或两者的某种组合,以便它们不同意使用 DHE 的密码套件;由于您的服务器是这里的错误服务器,因此我个人只会配置服务器。手册页再次说
cipher
但现实是ciphers
。由于 1.7.2.4 没有设置“tmp_ecdh”参数,并且(AFAICT)它不能使用 1.1.0,因此它不支持 ECDHE,这意味着如果没有 DHE,您的连接将不具有完美的前向保密性。如果您可以接受该限制,那么,ciphers='DEFAULT:!DHE'
在服务器上使用是一个简单的解决方案。(1.7.3.0 以上确实设置了“tmp_ecdh”并支持 ECDHE,即使它们没有默认 DH-1024 或更好,这也可以避免这里的问题,因为 ECDHE 套件优于 DHE,因此将选择 ECDHE,然后选择 DHE参数没有被使用并且无关紧要。)