2

(这是这个问题的延续,我解决了一个问题并发现了另一个问题)。

我正在通过 WireMock 代理使用 wget 获取 HTTPS 网站。这是我指向演示安全站点的 fetch 命令:

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

可以看到,获取失败,自动重试,需要取消才能结束。

我已经尝试--preserve-host-header过 WireMock 命令(这里的独立文档),但结果是一样的。

我想知道代理是否在内部失败,因为它需要指向有效的 HTTPS 证书存储?也就是说,我希望正在运行的代理会输出一些东西(甚至是错误),但它似乎根本没有处理调用。等效的 HTTP 调用可以正常工作。

我可以做些什么来看看为什么 Wget 失败了?错误消息不是很有帮助,据我所知,我不能让它更详细(wget 中默认情况下详细)。

这种行为在 Alpine 3.4(在 Docker 容器中)和在我的 Ubuntu 14.04 VM 上运行时是相同的。在 WireMock 2.4.1、2.5.0 和 2.5.1 中也是如此。

试用证书

我尝试将浏览器 (Firefox) 的 HTTPS 代理设置切换为指向 WireMock,但由于证书错误,它在我尝试获取的网站上失败。有趣的是,WireMock 不会向标准输出输出任何内容,即使看起来 Firefox 已经联系了远程服务器。

我想知道 Wiremock 中的内置密钥库是否已过时或为空,因此学习如何指定“真正的”证书存储可能是下一个值得尝试的事情。我使用这些说明浏览器证书文件转换为 JKS 格式,这对 Wget 或 Firefox 没有任何影响。

我注意到我新创建的密钥库是 955 字节,而原始 PEM 证书文件约为 260K,因此很明显并非所有证书都已添加(也许它只是添加了第一个?)。FWIW我使用了这个命令:

keytool -import -v -trustcacerts -alias endeca-ca \
    -file cacert.pem -keystore truststore.ks

正在到达确认代理

我在调用中添加了-verboseand-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,但各种输出似乎不太相关。我希望我对异常最感兴趣?

4

1 回答 1

3

我用 PHP 编写了自己的代理,并wget根据目标是 HTTP 还是 HTTPS 从代理端查看行为,这暴露了我的误解。

基本上,HTTP 客户端将使用标准方法(例如GETPOST)将(明文)HTTP 请求转发到代理,如果代理愿意(例如,出于播放目的),这些请求可以被代理捕获。这就是 WireMock 和其他类似工具会做的事情。

但是,如果 HTTP 客户端通过代理获取 HTTPS 目标,似乎需要使用该CONNECT方法,然后代理将充当双方之间的流量交换器 - 它有效地编组加密数据的交换,并且无法解码。

因此,这里可能的解释是 WireMock 不会费心处理这个动词,因为它无论如何都无法记录数据。

让我感到困惑的一个领域是,为什么 WireMock 提供了一个--https-port如果它无论如何都无法记录通过该端口的数据。如果我发现答案,我会更新这篇文章。

于 2017-04-04T21:40:48.933 回答