Privoxy 不适用于来自 iptables 的流量

Privoxy does not work with traffic from iptables

我已配置 privoxy 并在端口 8118 上工作。在定义 http_proxyhttps_proxy 变量以指向代理时,我可以转发 HTTP 和 HTTPS 流量。示例:

https_proxy=http://127.0.0.1:8118 curl -vvv https://www.google.com
http_proxy=http://127.0.0.1:8118 curl -vvv http://www.google.com

请注意,我仍然使用 http:// 作为 HTTPS 代理。 Privoxy 以某种方式转发请求。

但是,我需要透明转发,因为我正在使用Node.js,我不想更改应用程序代码以支持代理。在 Windows 上,这很容易由 Proxifier 完成,但该应用程序是专有的,不适用于 WSL 或 GNU/Linux。在 WSL/Linux 我尝试使用 iptables 将包转发到 privoxy 端口:

sudo iptables -t nat -N CUSTOM_PROXY

# Ignore LANs and some other reserved addresses.
sudo iptables -t nat -A CUSTOM_PROXY -d 0.0.0.0/8 -j RETURN
sudo iptables -t nat -A CUSTOM_PROXY -d 10.0.0.0/8 -j RETURN
sudo iptables -t nat -A CUSTOM_PROXY -d 127.0.0.0/8 -j RETURN
sudo iptables -t nat -A CUSTOM_PROXY -d 169.254.0.0/16 -j RETURN
sudo iptables -t nat -A CUSTOM_PROXY -d 172.16.0.0/12 -j RETURN
sudo iptables -t nat -A CUSTOM_PROXY -d 192.168.0.0/16 -j RETURN
sudo iptables -t nat -A CUSTOM_PROXY -d 224.0.0.0/4 -j RETURN
sudo iptables -t nat -A CUSTOM_PROXY -d 240.0.0.0/4 -j RETURN

# Everything else is redirected to the privoxy port
sudo iptables -t nat -A CUSTOM_PROXY -p tcp -j REDIRECT --to-ports 8118

# Then I tried to forward the ports I need to the chain:
sudo iptables -t nat -A OUTPUT -p tcp --dport 80 -j CUSTOM_PROXY
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j CUSTOM_PROXY

sudo iptables -t nat -A OUTPUT -p tcp --dport 443 -j CUSTOM_PROXY
sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j CUSTOM_PROXY

# other ports here...

激活这些规则后,HTTP 和 HTTPS 调用停止工作:

shell> curl -vvv http://www.google.com
*   Trying 142.250.74.36:80...
* TCP_NODELAY set
* Connected to www.google.com (142.250.74.36) port 80 (#0)
> GET / HTTP/1.1
> Host: www.google.com
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 400 Invalid header received from client
< Content-Type: text/plain
< Connection: close
< 
Invalid header received from client.
* Closing connection 0

shell> curl -vvv https://www.google.com
*   Trying 142.250.74.36:443...
* TCP_NODELAY set
* Connected to www.google.com (142.250.74.36) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3

HTTP 请求不起作用,HTTPS 请求永远不会结束。 Privoxy 也支持 socks5.

我不明白这些转发是如何发生的。有人可以帮我找出我做错了什么吗?

一些可能有用的额外 comments/questions:

我的 privoxy 设置使用所有默认值,除了以下转发配置:

forward  /  .
forward-socks5  .something.net  127.0.0.1:12345 .

我不认为这个 privoxy 配置真的很重要,因为我通过代理变量使用的任何东西都可以正常工作。问题出在iptables规则和privoxy之间。

感谢任何帮助。提前致谢!

我不完全了解 Privoxy 的工作原理,但我知道拦截代理在 Linux.
上的工作原理 HTTP 代理和拦截代理的工作方式截然不同。 HTTP 代理从查询的第一行获取目的地,其中包含域名(例如,它应该是 GET http://www.google.com/ HTTP/1.1)。对于 HTTPS,它会执行带有 domain:port 的 HTTP CONNECT 请求以连接到(例如 CONNECT www.google.com:443 HTTP/1.1)。
拦截代理通过使用一些特定参数执行 getsockopt() 从内核获取原始目标地址。它不了解更高级别的协议。
由于这些差异,通常使用 iptables 重定向到 HTTP 代理的请求不起作用。也就是说,Privoxy 似乎有一个配置选项 accept-intercepted-requests that you can use so it read the target from the Host: HTTP header. With that configuration, it should be able to handle HTTP requests redirected using iptables. As the documentation says, this is not supported for HTTPS. You will need to use some additional software which can do the forwarding to an HTTP proxy, probably much like Proxifier does. I know moproxy 可以做到这一点。应该不是唯一一个,其他的我不认识。

其他问题:

  • Why setting the variables works, and through iptables doesn't?

因为 HTTP 和 transparent/intercepting 代理的工作方式不同。当变量存在时,curl(和其他)会改变它们发送查询的方式,但是对于 iptables,它们不会(因为它们不知道您使用代理)。

  • Why do I have to set the https_proxy to point to http://...? Is that privoxy-related?

你的环境变量中的 http:// 是用来描述你如何连接到代理的(如果你的代理有 tls 证书,它实际上可能是 https:// ,它也适用于 http 请求,虽然它们只会从您到代理加密,而不是从代理到远程服务器)。

  • Regarding the comment "HTTPS is not supposed to be used with transparent proxies": So how does Proxifier work on Windows? If that is not transparent a proxy, is there another term for it? Why can't we have something similar on WSL/Linux?

我不知道透明代理在 Windows 上的具体工作方式。假设它的工作方式很像 Linux,Proxifier 可能会将请求重定向到本地端口,获取实际目的地,以 HTTP/SOCKS 代理可以理解的方式包装数据并将其发送到您指定的代理它使用。也许捕获部分有点不同(创建一个新的网络接口,要求 Windows 发送流量,从原始 tcp 数据包重建流,包装数据)。这通常称为透明代理,因为客户端不知道使用了代理,有些人将其称为拦截代理。我们可以有类似的东西,moproxy 就是一个例子(可能不是唯一的)