使用netcat发出的Squid代理丢弃请求,但不是curl

使用netcat发出的Squid代理丢弃请求,但不是curl,squid,netcat,Squid,Netcat,我需要在RHEL kickstart%pre脚本中进行REST调用,因此我只能使用netcat(因为RHEL%pre环境中打包的wget无法配置HTTP方法)。我当然喜欢使用curl(因为它有可爱的-X选项),但遗憾的是它在%pre环境中不可用 这就是说,这里有一个相关的curl命令,重要的是,它发送到服务器的确切字节流: $ curl -X POST http://pkrizak-globalpxe.anonycom.com/univac/api/record/pkrizak-sles10.a

我需要在RHEL kickstart
%pre
脚本中进行REST调用,因此我只能使用netcat(因为RHEL
%pre
环境中打包的
wget
无法配置HTTP方法)。我当然喜欢使用
curl
(因为它有可爱的
-X
选项),但遗憾的是它在
%pre
环境中不可用

这就是说,这里有一个相关的
curl
命令,重要的是,它发送到服务器的确切字节流:

$ curl -X POST http://pkrizak-globalpxe.anonycom.com/univac/api/record/pkrizak-sles10.anonycom.com/_install_log --data-binary '[ ]' --trace /tmp/foo.log
$ cat /tmp/foo.log (truncated)
== Info: About to connect() to pkrizak-globalpxe.anonycom.com port 80 (#0)
== Info:   Trying 10.46.174.117... == Info: connected
== Info: Connected to pkrizak-globalpxe.anonycom.com (10.46.174.117) port 80 (#0)
=> Send header, 312 bytes (0x138)
0000: 50 4f 53 54 20 2f 75 6e 69 76 61 63 2f 61 70 69 POST /univac/api
0010: 2f 72 65 63 6f 72 64 2f 70 6b 72 69 7a 61 6b 2d /record/pkrizak-
0020: 73 6c 65 73 31 30 2e 61 63 6f 63 79 63 6f 6d 2e sles10.anonycom.
0030: 63 6f 6d 2f 5f 69 6e 73 74 61 6c 6c 5f 6c 6f 67 com/_install_log
0040: 20 48 54 54 50 2f 31 2e 31 0d 0a 55 73 65 72 2d  HTTP/1.1..User-
0050: 41 67 65 6e 74 3a 20 63 75 72 6c 2f 37 2e 31 39 Agent: curl/7.19
0060: 2e 37 20 28 78 38 36 5f 36 34 2d 72 65 64 68 61 .7 (x86_64-redha
0070: 74 2d 6c 69 6e 75 78 2d 67 6e 75 29 20 6c 69 62 t-linux-gnu) lib
0080: 63 75 72 6c 2f 37 2e 31 39 2e 37 20 4e 53 53 2f curl/7.19.7 NSS/
0090: 33 2e 31 34 2e 33 2e 30 20 7a 6c 69 62 2f 31 2e 3.14.3.0 zlib/1.
00a0: 32 2e 33 20 6c 69 62 69 64 6e 2f 31 2e 31 38 20 2.3 libidn/1.18 
00b0: 6c 69 62 73 73 68 32 2f 31 2e 34 2e 32 0d 0a 48 libssh2/1.4.2..H
00c0: 6f 73 74 3a 20 70 6b 72 69 7a 61 6b 2d 67 6c 6f ost: pkrizak-glo
00d0: 62 61 6c 70 78 65 2e 61 63 6f 63 79 63 6f 6d 2e balpxe.anonycom.
00e0: 63 6f 6d 0d 0a 41 63 63 65 70 74 3a 20 2a 2f 2a com..Accept: */*
00f0: 0d 0a 43 6f 6e 74 65 6e 74 2d 4c 65 6e 67 74 68 ..Content-Length
0100: 3a 20 33 0d 0a 43 6f 6e 74 65 6e 74 2d 54 79 70 : 3..Content-Typ
0110: 65 3a 20 61 70 70 6c 69 63 61 74 69 6f 6e 2f 78 e: application/x
0120: 2d 77 77 77 2d 66 6f 72 6d 2d 75 72 6c 65 6e 63 -www-form-urlenc
0130: 6f 64 65 64 0d 0a 0d 0a                         oded....
=> Send data, 3 bytes (0x3)
0000: 5b 20 5d                                        [ ]
== Info: HTTP 1.0, assume close after body
<= Recv header, 24 bytes (0x18)
…不起作用:

$ ./mypost.sh | nc pkrizak-globalpxe.anonycom.com 80
$ # no response
这里比较棘手的一点是,在我连接的主机的端口80上有一个squid(反向)代理正在侦听。因此,我实际上不是在与Apache或Nginx,甚至不是我的定制Perl应用程序交谈——我试图与Squid交谈(当使用
curl
时,Squid实际上会将请求正确地转发给我的应用程序)。显然,curl与Squid的对话方式与nc与Squid的对话方式有所不同,尽管请求的内容相同

我尝试将请求更改为使用
HTTP/1.0
,甚至尝试关闭
HTTP/
部分,但这没有帮助


在这一点上我真的很困惑——我所错过的引擎盖下到底发生了什么?为什么netcat的行为会有所不同?

事实证明,在STDIN上传输数据时,netcat的行为方式很奇怪

在使用wireshark跟踪数据包之后,我发现netcat在通过管道将数据发送到STDIN后,立即向服务器发送FIN、ACK数据包。squid服务器自然会在收到FIN、ACK数据包后中止请求处理,并关闭连接

通过使用netcat的
-i
选项可以避免这种行为,该选项指定事务之间的间隔时间。例如,使用
-i 1
,在发送FIN之前等待一秒钟,在发送数据之后等待确认。这足够长,squid代理返回一个答案

另一种解决方案是让生成STDIN输入的脚本在写出httppost信息后暂停。脚本末尾的一个简单的
sleep 1
似乎足以让代理完成请求

$ ./mypost.sh | nc pkrizak-globalpxe.anonycom.com 80
$ # no response