免责声明:我没有太多代理经验,因此我可能会忽略一些显而易见的事情。在询问之前,我已尽力做好应尽的调查。
简短版本 - 基本问题
我在“设置”->“网络”->“代理”中将本地文件指定为“自动”配置 URL 时遇到问题。
我已经验证,如果我使用“手动”,然后输入代理服务器的 IP 地址/端口,我的流量将通过代理正确路由,但该路由全部通过代理传输流量,我只想针对特定网站执行此操作。据我所知,最好的方法是使用 PAC 文件。我编写了一个我认为有效的文件,并将其保存到:$HOME/.config/custom_proxy/my-proxy.js
。在“配置 URL”中,我尝试将其设置为几个值,但没有一个“有效”。我试过:
file:///home/joncrall/.config/custom_proxy/my-proxy.js
file://localhost/home/joncrall/.config/custom_proxy/my-proxy.js
/home/joncrall/.config/custom_proxy/my-proxy.js
我只想将 PAC 文件保存在本地磁盘的某个位置。我的指定是否不正确?
长版——动机和问题
激励用例是,我的笔记本电脑上有 VPN,而我在台式机上工作,台式机没有 VPN。我的笔记本电脑和台式机都在同一个 LAN 上。我希望特定网站的流量通过笔记本电脑路由,这样它们就可以有效地使用 VPN,但其他所有事情我都希望使用直接连接。据我所知,这是一个典型的代理案例。
我在笔记本电脑上运行命令ssh -N -D 0.0.0.0:1080 localhost
,我相信这会将其变成代理服务器。我认为这是我在笔记本电脑端需要做的所有事情,除了确保它已打开并连接到 VPN。
在我的桌面(即代理客户端)上,我编写了一个 PAC 文件,如下所示:
echo '
function FindProxyForURL(url, host) {
var socks_proxy = "SOCKS 192.168.1.3:1080";
if (shExpMatch(host, "*.special-site1.com")) {
return socks_proxy;
}
else if (shExpMatch(host, "*.special-site2.net")) {
return socks_proxy;
}
else if (shExpMatch(host, "special-site1.com")) {
return socks_proxy;
}
return "DIRECT";
}
' > "$HOME"/.config/custom_proxy/my-proxy.js
为了将 Ubuntu 的网络管理器指向这个 PAC 文件,我进行了 GUI 导航:
Settings -> Network -> Proxy
启用“网络代理”
将配置更改为“自动”
输入了 URI:file:///home/joncrall/.config/custom_proxy/my-proxy.js
单击“保存”。
这不起作用。我尝试导航到 VPN 后面的站点,DNS 探测失败。
我也尝试了其他方法来指定 URI:
file:///home/joncrall/.config/custom_proxy/my-proxy.js
file://localhost/home/joncrall/.config/custom_proxy/my-proxy.js
/home/joncrall/.config/custom_proxy/my-proxy.js
这些都不起作用。
采取的调试步骤
如果我将配置更改为“手动”,然后在“SOCKS 主机”下输入 URL:192.168.1.3
和端口:1080
,并保留 http、https、ftp 和忽略的主机设置,做似乎有效。我能够访问相关网站。但这种方法太繁重了。它会路由所有流量,我想要更多的控制权,所以只有一些网站通过代理。
我不确定我的 PAC 文件出了什么问题。我已验证这似乎是有效的语法,可以使用以下命令执行我想要的操作pacparser
:
python -c "if 1:
import pacparser
pacparser.init()
pacparser.parse_pac('/home/joncrall/.config/custom_proxy/my-proxy.js')
print(pacparser.find_proxy('http://www.google.com', 'www.google.com'))
print(pacparser.find_proxy('https://subdomain.special-site1.com/foobar'))
print(pacparser.find_proxy('https://special-site1.com'))
print(pacparser.find_proxy('https://special-site2.net'))
print(pacparser.find_proxy('https://foo.special-site2.net'))
"
它打印:
DIRECT
SOCKS 192.168.1.3:1080
SOCKS 192.168.1.3:1080
DIRECT
SOCKS 192.168.1.3:1080
这正是我所期望的。它通过列表中没有的两个站点,另一个站点将地址返回给代理。
我也尝试my-proxy.js
通过 http 服务器公开我的自定义。要启动服务器,我运行了:
cd "$HOME"/.config/custom_proxy/
sudo python3 -m http.server 80
然后我通过以下方式修改了“配置 URL”:
gsettings set org.gnome.system.proxy autoconfig-url "http://localhost/my-proxy.js"
这样做确实导致我的 python http 服务器打印输出,表明某些东西对 my-proxy.js 文件执行了 GET。这表明网络管理器正在读取 PAC 文件,但它似乎没有正确路由流量。
我想知道是否有任何方法可以在 PAC 文件本身内进行打印调试?或者是否有任何方法可以检查网络管理器是否正在尝试使用它?
系统信息:
我在使用 Ubuntu 24.04。
为了寻找答案,我查阅过的参考资料是:
- https://serverfault.com/questions/62261/can-i-configure-ubuntu-to-use-a-proxy-for-a-subset-of-websites
- https://findproxyforurl.com/pac-functions/
- https://gist.github.com/swinton/5a66c283fd011af7f67a
- 如何使我的代理设置根据我所连接的网络而改变?
- https://superuser.com/questions/191037/local-pac-file-url-format-that-works-with-ie-and-safari-windows
- https://wiki.gentoo.org/wiki/ProxyAutoConfig
- https://github.com/manugarg/pacparser
但我遇到了麻烦。我指定 PAC 文件的方式或文件内容是否有问题?
答案1
您的问题是关于如何配置 PAC 文件。让我们先了解一下您实际要做什么。
根据代理自动配置在维基百科上:
代理自动配置 (PAC) 文件定义了 Web 浏览器和其他用户代理如何自动选择适当的代理服务器(访问方法)来获取给定的 URL。
因此,这意味着 PAC 文件允许浏览器或其他代理根据某些预定义函数和环境条件。这些条件可能因特定主机名、IP 地址甚至基于时间的条件而异。
此外,PAC 文件条件返回特定格式的字符串返回值格式。此字符串的格式为 DIRECT、PROXY、SOCKS、HTTP、HTTPS、SOCKS4 或 SOCKS5。
因此,当我检查你的 PAC 文件时,你指定了 SOCKS 返回值格式,当条件为匹配结果与多个主机之一匹配。否则,它将返回 DIRECT。
为了解决您的问题,我们首先要将 PAC 文件从方程式中剔除,然后设置一个简单的 SSH SOCKS 隧道,将其连接到将作为我们的代理服务器的服务器。配置并运行后,我们将更改您的设置,使其根据您的 PAC 文件条件自动选择代理服务器。
设置 SSH SOCKS 隧道
Linuxize 上的一篇文章概述了设置 SSH SOCKS 隧道的基本说明,标题为:如何设置 SSH SOCKS 隧道以实现隐私浏览。
先决条件是服务器和客户端。
服务器
- 任何版本的 Linux
openssh-server
已安装sshd
在某个端口上运行,通常是端口 22- 从互联网访问指定端口上的服务器,通常为端口 22
- 访问互联网
客户
openssh-client
已安装- 访问互联网
创建隧道
此时,使用以下命令创建 SSH SOCKS 隧道非常容易,该命令运行在客户端上。
ssh -D 8080 [USER]@[SERVER_IP]
这将创建到服务器的 SSH 连接和端口上的 SOCKS 隧道8080
。这意味着指向127.0.0.1
端口的客户端流量8080
将被重定向到服务器。
根据ssh(1) 手册页:
-D [bind_address:]port
Specifies a local “dynamic” application-level port
forwarding. This works by allocating a socket to listen
to port on the local side, optionally bound to the
specified bind_address. Whenever a connection is made to
this port, the connection is forwarded over the secure
channel, and the application protocol is then used to
determine where to connect to from the remote machine.
Currently the SOCKS4 and SOCKS5 protocols are supported,
and will act as a SOCKS server. Only root can forward
privileged ports. Dynamic port forwardings can also be
specified in the configuration file.
您可以添加到ssh
命令的其他适当选项是-f
和-N
。
-f Requests to go to background just before command
execution. This is useful if is going to ask for
passwords or passphrases, but the user wants it in the
background. This implies -n. The recommended way to
start X11 programs at a remote site is with something
like ssh -f host xterm.
-N Do not execute a remote command. This is useful for just
forwarding ports. Refer to the description of
SessionType in ssh_config(5) for details.
做记录:服务器上无需执行任何操作。只要您能够ssh
进入,您就可以创建 SSH SOCKS 隧道并将服务器视为代理。
设置浏览器
有两种方法可以配置浏览器以使用 SOCKS 代理。一种是手动指定 SOCKS 代理。另一种是使用 Gnome 系统网络设置,然后配置 Firefox 以使用系统设置。我将概述这两种方法。
选项 1:在 Firefox 中手动指定 SOCKS 代理
要配置浏览器以手动指定 SOCKS 代理,请执行以下操作:
- 在 Firefox 中,转到常规/网络设置/设置, 选择手动代理,并
127.0.0.1
输入SOCKS主机以及8080
港口。 - 勾选单选框袜子v5。
- 勾选使用 SOCKS 5 时的代理 DNS。这也会将任何 DNS 查询发送到隧道。单击好的去完成。
您的 SSH SOCKS 隧道应已设置并正常运行。所有流量将通过 SSH SOCKS 隧道定向到您的服务器,并从该网络传到互联网。
如果你去https://whatismyipaddress.com/,这应该可以确认您的 IP 地址是代理服务器的公共 IP,而不是客户端的 IP。您可以将浏览器设置改回无代理再看看https://whatismyipaddress.com/以确认它们是不同的。
- 如果你切断 SSH 连接,你的客户端浏览器会收到一条错误消息,提示代理服务器拒绝连接。
- 如果 SSH 连接和隧道已启动,但您仍然无法从客户端浏览器访问互联网,则说明您的服务器无法访问互联网。返回开始并确认您的服务器可以访问互联网。
选项 2:配置 Firefox 以使用 Gnome 系统设置
或者,您可以在 Gnome 系统设置中配置 SOCKS 代理。为此,首先打开 Gnome设置/网络/网络代理,选择Manual
代理配置,并127.0.0.1
输入SOCKS 主机 URL以及8080
SOCKS 主机端口。接下来,localhost, 127.0.0.0/8, ::1
删除忽略的主机字段(或仅localhost
)。最后,点击节省。
然后在 Firefox 中,转到常规/网络设置/设置并选择使用系统代理设置。
设置代理自动配置的 PAC 文件
要切换到使用 PAC 文件自动选择代理服务器很简单,只需更改浏览器和/或 Gnome 系统设置中的设置以使用 PAC 文件,而不是为所有流量手动指定 SOCKS 代理即可。
做记录:如果您无法让 SSH SOCKS 隧道与您的代理服务器配合使用,那么自动选择代理服务器以使用您的代理服务器的设置将不起作用。因此,请先让 SSH SOCKS 隧道正常工作。然后使用 PAC 文件切换到自动。
让我们从文件开始...
在您的问题中,您创建了一个名为的文件my-proxy.js
。在下面的示例中,我将其重命名为proxy.pac
并将其放在我的主目录中:/home/mike/proxy.pac
。
根据Mozilla 文档为了代理自动配置 (PAC) 文件,PAC 文件应该以.pac
扩展名命名。但在我的测试中,这不是强制性的,因为我.js
像您一样成功使用了扩展名。
自动配置文件应保存为带有 .pac 文件扩展名的文件:proxy.pac。
配置
与以前为所有流量设置 SOCKS 代理一样,设置 PAC 文件的配置可以通过两种方式完成。
在这两个选项中,URL 的格式相同:
file:///home/mike/proxy.pac
选项 1:在 Firefox 中手动指定 PAC 文件
在 Firefox 中,转到常规/网络设置/设置并file:///home/mike/proxy.pac
输入自动代理配置 URL字段。我发现只需单击“确定”并关闭设置窗口即可。但您可能会发现需要完全关闭并重新加载浏览器,尤其是第一次设置 URL 时。后续更改和重新加载足以让我看到任何变化生效。
选项 2:配置 Firefox 以使用 Gnome 系统设置
或者,您可以在 Gnome 系统设置中配置 SOCKS 代理。为此,首先打开 Gnome设置/网络/网络代理,选择Automatic
代理配置,并file:///home/mike/proxy.pac
输入配置 URL。
然后在 Firefox 中,转到常规/网络设置/设置并选择使用系统代理设置。
测试
这是在 Ubuntu 24.04 Desktop 上测试的。使用以下命令创建了到个人服务器的 SSH SOCKS 隧道。这在客户端计算机上运行。
ssh -D 8080 [USER]@[SERVER_IP]
我用于测试的具体.pac
文件如下:
function FindProxyForURL(url, host)
{
var socks_proxy = "SOCKS 127.0.0.1:8080";
if (shExpMatch(host, "*.askubuntu.com")) {
return socks_proxy;
}
return "DIRECT";
}
我通过tcpdump -n net 172.64.150
在代理服务器上运行进行了确认。IP 子网是通过nslookup askubuntu.com
在代理服务器上运行收集的。
$ nslookup askubuntu.com
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
Name: askubuntu.com
Address: 172.64.150.156
Name: askubuntu.com
Address: 104.18.37.100
在使用此配置进行测试期间,流量askubuntu.com
被定向到我的代理服务器。所有其他流量均未定向。
另一个简单的测试是断开ssh
连接。在这种情况下,您将无法访问askubuntu.com
。