如何在 wget 中调试 HTTPS 代理失败?
How to debug a HTTPS proxy failure in wget?
(这是一个,解决了一个问题,发现了另一个问题)。
我正在通过 WireMock 代理使用 wget 获取 HTTPS 网站。这是我指向演示安全站点的获取命令:
wget -e use_proxy=yes -e https_proxy=localhost:8100 \
https://www.rottentomatoes.com/
这是我的代理设置:
java -jar wiremock-standalone-2.5.1.jar \
--port 8081 --https-port 8100 \
--proxy-all https://www.rottentomatoes.com/ \
--record-mappings \
--root-dir ./proxy-cache \
--verbose
WireMock 屏幕日志是这样说的:
2017-03-27 12:08:09.066 Verbose logging enabled
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
2017-03-27 12:08:09.827 Verbose logging enabled
2017-03-27 12:08:09.892 Recording mappings to ./proxy-cache/mappings
/$$ /$$ /$$ /$$ /$$ /$$
| $$ /$ | $$|__/ | $$$ /$$$ | $$
| $$ /$$$| $$ /$$ /$$$$$$ /$$$$$$ | $$$$ /$$$$ /$$$$$$ /$$$$$$$| $$ /$$
| $$/$$ $$ $$| $$ /$$__ $$ /$$__ $$| $$ $$/$$ $$ /$$__ $$ /$$_____/| $$ /$$/
| $$$$_ $$$$| $$| $$ \__/| $$$$$$$$| $$ $$$| $$| $$ \ $$| $$ | $$$$$$/
| $$$/ \ $$$| $$| $$ | $$_____/| $$\ $ | $$| $$ | $$| $$ | $$_ $$
| $$/ \ $$| $$| $$ | $$$$$$$| $$ \/ | $$| $$$$$$/| $$$$$$$| $$ \ $$
|__/ \__/|__/|__/ \_______/|__/ |__/ \______/ \_______/|__/ \__/
port: 8081
https-port: 8100
https-keystore: jar:file:(removed)/wiremock-standalone-2.5.1.jar!/keystore
proxy-all: https://www.rottentomatoes.com/
preserve-host-header: false
enable-browser-proxying: false
record-mappings: true
match-headers: []
no-request-journal: false
verbose: true
结果是:
--2017-03-27 12:08:25-- https://www.rottentomatoes.com/
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:8100... connected.
Failed reading proxy response: Success
Retrying.
--2017-03-27 12:08:26-- (try: 2) https://www.rottentomatoes.com/
Connecting to localhost (localhost)|127.0.0.1|:8100... connected.
Failed reading proxy response: Success
Retrying.
^C
可以看到,fetch失败,自动重试,需要取消才能结束
我在 WireMock 命令中尝试了 --preserve-host-header
(standalone docs here),但结果是一样的。
我想知道代理是否在内部失败,因为它需要指向一个有效的 HTTPS 证书存储?也就是说,我希望 运行ning 代理输出一些东西(甚至是错误),但它似乎根本没有处理调用。等效的 HTTP 调用工作正常。
我能做些什么来了解 Wget 失败的原因吗?错误消息不是很有帮助,据我所知我不能让它更详细(详细在 wget 中默认打开)。
Alpine 3.4(在 Docker 容器中)和我的 Ubuntu 14.04 VM 上的 运行ning 中的这种行为是相同的。它在 WireMock 2.4.1、2.5.0 和 2.5.1 中也是相同的。
正在尝试证书
我已尝试将浏览器 (Firefox) 的 HTTPS 代理设置切换为指向 WireMock,但由于证书错误,它在我尝试获取的网站上失败。有趣的是 WireMock 不会向标准输出输出任何内容,即使它看起来像 Firefox 已经联系了远程服务器。
我想知道 Wiremock 中的内置密钥库是否已过时或为空,因此学习如何指定 "real" 证书存储可能是接下来值得尝试的事情。我将 these instructions to convert a browser cert file 用于 JKS 格式,这对 Wget 或 Firefox 没有影响。
我注意到我新创建的密钥库是 955 字节,而原始 PEM 证书文件是 ~260K,所以很明显并不是所有的证书都被添加了(也许它只是添加了第一个?)。 FWIW 我使用了这个命令:
keytool -import -v -trustcacerts -alias endeca-ca \
-file cacert.pem -keystore truststore.ks
正在确认代理
我已将 -verbose
和 -verbose:jni
开关添加到 java
调用,以证明在需要 HTTPS 代理时发生了某些事情。当我 运行 Wget 命令时打印出一篇名副其实的文章,所以我确信 HTTPS 代理被命中。 Wget 在 HTTP 模式下也可以正常获取。
如何记录独立 Jar 文件中发生的事情?
我正处于可以盲目尝试各种事情的阶段,我想我需要从 Java 系统中获得一些情报来了解 为什么 它首先失败。我的猜测是 Wiremock 是问题所在,而不是 Wget。
我在 Wiremock --print-all-network-traffic
中发现了一个未记录的功能,它提供了这个:
2017-03-27 17:36:51.287 Opened Socket[addr=/127.0.0.1,port=54140,localport=8100]
2017-03-27 17:36:51.397 Incoming bytes: CONNECT www.rottentomatoes.com:443 HTTP/1.1
User-Agent: Wget/1.15 (linux-gnu)
Host: www.rottentomatoes.com:443
2017-03-27 17:36:51.398 Closed Socket[addr=/127.0.0.1,port=54140,localport=8100]
2017-03-27 17:36:51.399 Closed Socket[addr=/127.0.0.1,port=54140,localport=8100]
2017-03-27 17:36:52.400 Opened Socket[addr=/127.0.0.1,port=54142,localport=8100]
2017-03-27 17:36:52.483 Incoming bytes: CONNECT www.rottentomatoes.com:443 HTTP/1.1
User-Agent: Wget/1.15 (linux-gnu)
Host: www.rottentomatoes.com:443
第二部分的重复次数与 wget 重试次数一样多,但这里仍然没什么用处。我想知道为什么它失败了。
是否有我可以添加到 java -jar
的日志记录参数,或者是否有 Java 的系统范围错误日志可供我参考?我已经安装了 VisualVM,但各种输出似乎不太相关。我希望我对异常最感兴趣?
我在 PHP 中写了自己的代理,根据目标是 HTTP 还是 HTTPS 从代理端看到 wget
的行为,揭示了我在这里的误解。
基本上,HTTP 客户端会使用标准方法(例如 GET
或 POST
)将(明文)HTTP 请求转发给代理,如果代理愿意,可以捕获这些请求(例如用于播放目的)。这就是 WireMock 和其他类似工具的作用。
但是,如果HTTP客户端通过代理获取HTTPS目标,似乎需要使用CONNECT
方法,然后代理将充当双方之间的流量交换器 -它有效地编组加密数据的交换,并且无法对其进行解码。
因此,这里可能的解释是 WireMock 懒得处理这个动词,因为它无论如何也无法记录数据。
让我感到困惑的一个方面是,如果 WireMock 无法记录通过该端口的数据,为什么会提供 --https-port
。如果我找到答案,我会更新这个 post。
(这是一个
我正在通过 WireMock 代理使用 wget 获取 HTTPS 网站。这是我指向演示安全站点的获取命令:
wget -e use_proxy=yes -e https_proxy=localhost:8100 \
https://www.rottentomatoes.com/
这是我的代理设置:
java -jar wiremock-standalone-2.5.1.jar \
--port 8081 --https-port 8100 \
--proxy-all https://www.rottentomatoes.com/ \
--record-mappings \
--root-dir ./proxy-cache \
--verbose
WireMock 屏幕日志是这样说的:
2017-03-27 12:08:09.066 Verbose logging enabled
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
2017-03-27 12:08:09.827 Verbose logging enabled
2017-03-27 12:08:09.892 Recording mappings to ./proxy-cache/mappings
/$$ /$$ /$$ /$$ /$$ /$$
| $$ /$ | $$|__/ | $$$ /$$$ | $$
| $$ /$$$| $$ /$$ /$$$$$$ /$$$$$$ | $$$$ /$$$$ /$$$$$$ /$$$$$$$| $$ /$$
| $$/$$ $$ $$| $$ /$$__ $$ /$$__ $$| $$ $$/$$ $$ /$$__ $$ /$$_____/| $$ /$$/
| $$$$_ $$$$| $$| $$ \__/| $$$$$$$$| $$ $$$| $$| $$ \ $$| $$ | $$$$$$/
| $$$/ \ $$$| $$| $$ | $$_____/| $$\ $ | $$| $$ | $$| $$ | $$_ $$
| $$/ \ $$| $$| $$ | $$$$$$$| $$ \/ | $$| $$$$$$/| $$$$$$$| $$ \ $$
|__/ \__/|__/|__/ \_______/|__/ |__/ \______/ \_______/|__/ \__/
port: 8081
https-port: 8100
https-keystore: jar:file:(removed)/wiremock-standalone-2.5.1.jar!/keystore
proxy-all: https://www.rottentomatoes.com/
preserve-host-header: false
enable-browser-proxying: false
record-mappings: true
match-headers: []
no-request-journal: false
verbose: true
结果是:
--2017-03-27 12:08:25-- https://www.rottentomatoes.com/
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:8100... connected.
Failed reading proxy response: Success
Retrying.
--2017-03-27 12:08:26-- (try: 2) https://www.rottentomatoes.com/
Connecting to localhost (localhost)|127.0.0.1|:8100... connected.
Failed reading proxy response: Success
Retrying.
^C
可以看到,fetch失败,自动重试,需要取消才能结束
我在 WireMock 命令中尝试了 --preserve-host-header
(standalone docs here),但结果是一样的。
我想知道代理是否在内部失败,因为它需要指向一个有效的 HTTPS 证书存储?也就是说,我希望 运行ning 代理输出一些东西(甚至是错误),但它似乎根本没有处理调用。等效的 HTTP 调用工作正常。
我能做些什么来了解 Wget 失败的原因吗?错误消息不是很有帮助,据我所知我不能让它更详细(详细在 wget 中默认打开)。
Alpine 3.4(在 Docker 容器中)和我的 Ubuntu 14.04 VM 上的 运行ning 中的这种行为是相同的。它在 WireMock 2.4.1、2.5.0 和 2.5.1 中也是相同的。
正在尝试证书
我已尝试将浏览器 (Firefox) 的 HTTPS 代理设置切换为指向 WireMock,但由于证书错误,它在我尝试获取的网站上失败。有趣的是 WireMock 不会向标准输出输出任何内容,即使它看起来像 Firefox 已经联系了远程服务器。
我想知道 Wiremock 中的内置密钥库是否已过时或为空,因此学习如何指定 "real" 证书存储可能是接下来值得尝试的事情。我将 these instructions to convert a browser cert file 用于 JKS 格式,这对 Wget 或 Firefox 没有影响。
我注意到我新创建的密钥库是 955 字节,而原始 PEM 证书文件是 ~260K,所以很明显并不是所有的证书都被添加了(也许它只是添加了第一个?)。 FWIW 我使用了这个命令:
keytool -import -v -trustcacerts -alias endeca-ca \
-file cacert.pem -keystore truststore.ks
正在确认代理
我已将 -verbose
和 -verbose:jni
开关添加到 java
调用,以证明在需要 HTTPS 代理时发生了某些事情。当我 运行 Wget 命令时打印出一篇名副其实的文章,所以我确信 HTTPS 代理被命中。 Wget 在 HTTP 模式下也可以正常获取。
如何记录独立 Jar 文件中发生的事情?
我正处于可以盲目尝试各种事情的阶段,我想我需要从 Java 系统中获得一些情报来了解 为什么 它首先失败。我的猜测是 Wiremock 是问题所在,而不是 Wget。
我在 Wiremock --print-all-network-traffic
中发现了一个未记录的功能,它提供了这个:
2017-03-27 17:36:51.287 Opened Socket[addr=/127.0.0.1,port=54140,localport=8100]
2017-03-27 17:36:51.397 Incoming bytes: CONNECT www.rottentomatoes.com:443 HTTP/1.1
User-Agent: Wget/1.15 (linux-gnu)
Host: www.rottentomatoes.com:443
2017-03-27 17:36:51.398 Closed Socket[addr=/127.0.0.1,port=54140,localport=8100]
2017-03-27 17:36:51.399 Closed Socket[addr=/127.0.0.1,port=54140,localport=8100]
2017-03-27 17:36:52.400 Opened Socket[addr=/127.0.0.1,port=54142,localport=8100]
2017-03-27 17:36:52.483 Incoming bytes: CONNECT www.rottentomatoes.com:443 HTTP/1.1
User-Agent: Wget/1.15 (linux-gnu)
Host: www.rottentomatoes.com:443
第二部分的重复次数与 wget 重试次数一样多,但这里仍然没什么用处。我想知道为什么它失败了。
是否有我可以添加到 java -jar
的日志记录参数,或者是否有 Java 的系统范围错误日志可供我参考?我已经安装了 VisualVM,但各种输出似乎不太相关。我希望我对异常最感兴趣?
我在 PHP 中写了自己的代理,根据目标是 HTTP 还是 HTTPS 从代理端看到 wget
的行为,揭示了我在这里的误解。
基本上,HTTP 客户端会使用标准方法(例如 GET
或 POST
)将(明文)HTTP 请求转发给代理,如果代理愿意,可以捕获这些请求(例如用于播放目的)。这就是 WireMock 和其他类似工具的作用。
但是,如果HTTP客户端通过代理获取HTTPS目标,似乎需要使用CONNECT
方法,然后代理将充当双方之间的流量交换器 -它有效地编组加密数据的交换,并且无法对其进行解码。
因此,这里可能的解释是 WireMock 懒得处理这个动词,因为它无论如何也无法记录数据。
让我感到困惑的一个方面是,如果 WireMock 无法记录通过该端口的数据,为什么会提供 --https-port
。如果我找到答案,我会更新这个 post。