Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python标准输出到openssl子进程的文件_Python_Ssl_Openssl_Subprocess_Stdout - Fatal编程技术网

Python标准输出到openssl子进程的文件

Python标准输出到openssl子进程的文件,python,ssl,openssl,subprocess,stdout,Python,Ssl,Openssl,Subprocess,Stdout,我正试图编写一个python脚本,通过openSSL自动检查SSL重新协商的过程,并将结果输出到一个文件中。我遇到了两个问题 我的第一个问题是,初始握手的输出会写入文件,但实际的重新协商部分不会。而是显示在控制台上 subprocess.call("echo \"R\" | openssl s_client -connect example.com:443", shell=True, stdout=FILE) 我的另一个问题(尽管这可能是错误的地方)是我无法使用openSSL

我正试图编写一个python脚本,通过openSSL自动检查SSL重新协商的过程,并将结果输出到一个文件中。我遇到了两个问题

我的第一个问题是,初始握手的输出会写入文件,但实际的重新协商部分不会。而是显示在控制台上

subprocess.call("echo \"R\" | openssl s_client -connect example.com:443", 
        shell=True, stdout=FILE)
我的另一个问题(尽管这可能是错误的地方)是我无法使用openSSL命令来发送get命令

subprocess.call("echo -e \"GET / HTTP/1.1\r\n\r\n\" | openssl s_client -connect
        example.com:443", shell=True)   
同样,初始连接已建立,但存在openSSL,它不处理GET请求


任何帮助都将不胜感激。谢谢。

没有理由对输入使用
shell=True
。相反,请使用
stdin=subprocess.PIPE
。另外,请注意,您的请求无效,因为HTTP 1.1需要
Host
头。此外,我想不出使用命令行openssl而不是

话虽如此,这里有一个有效的例子:

import subprocess

f = open('http_answer', 'w')
_,log = subprocess.Popen(
    ['openssl', 's_client', '-quiet', '-connect', 'twitter.com:443'],
    stdout=f, stderr=subprocess.PIPE, stdin=subprocess.PIPE
).communicate('GET / HTTP/1.0\r\n\r\n')
print('Output of SSL:\n' + log)

请记住,openssl s_客户机还将stderr用于某些输出。你需要检查重新谈判是否会进入stderr,我相信会的,尽管我的记忆可能正在衰退

我以不同的方式实现了这一点,尽管不是用python实现的。我已经创建了一个进程,并将stdin、stdout、stderr文件描述符连接到我可以读/写的文件描述符上,我实际驱动输入并读取输出。这需要更多的工作,但您可以完全控制正在发生的事情以及与流程的交互。我已经在php中完成了这项测试,该测试可在线访问

或者,您可以尝试使用python来编程openssl本身,而不是使用s_客户机,但这是更多的工作,我使用了前面的方法

有两件事你可以检查,但你没有明确说明你对哪一件感兴趣:

  • 检查远程服务器是否支持客户端启动的重新协商
  • 正在检查远程服务器是否支持安全重新协商扩展

只要对这两种情况下适用的关键字执行s_client和grep,就可以简单地推断出这两种情况。这完全取决于你需要多大的控制力/复杂度。

@phihag我对你的纸条做了一些小改动,对我来说效果很好

import subprocess

f = open('http_answer', 'w')
_,log = subprocess.Popen(
    ['openssl', 's_client', '-quiet', '-connect', 'twitter.com:443','-sess_out', 'session.txt'],
    stdout=f, stderr=subprocess.PIPE, stdin=subprocess.PIPE ).communicate('GET / HTTP/1.0\r\nHOST: twitter.com\r\n\r\n') print('Output of SSL:\n' + log)
列出更改 1.添加了“sess_out”“session.txt”参数,该参数保留了所有SSL会话参数,可以使用以下openssl命令查看这些参数

$openssl sess_id -in test.txt -text -cert -noout
  • 在GET命令中添加了主机信息,因为较新的部分仅使用主机选项才能很好地响应

    'GET/HTTP/1.0\r\nHOST:twitter.com\r\n\r\n'


  • @Drew,太晚了,但我希望这有点帮助。谢谢。

    有什么理由不使用python ssl包装器吗?也许你可以用它得到更好的调试信息。只是一个想法。SSL模块并没有给你足够的控制力来迫使重新协商在被发送的请求的中间,或者至少我上次找不到一个方法。我用HTTP 1和1.1尝试了它,它似乎给了我和以前一样的结果。get请求仍未被处理。编辑:我没有使用ssl模块,因为我们在这里使用openSSL进行许多不同的测试,我想保持它的一致性。@Drew如果您执行答案中发布的确切代码,是否会得到一个文件
    http\u answer
    ?是的,它会输出s\u客户端命令的结果,但实际上不会处理get请求。它只是在握手时停止。@Drew你怎么知道它不处理GET请求?但是,如果上述代码不起作用,则说明您的openssl安装或证书存储有问题。在未触及的VM或chroot中尝试它。我正在尝试测试服务器是否允许客户端启动重新协商。你说得对。谢谢