Skip to content
Back

如何让服务器通过本地代理连通外网

AI 总结

当服务器无法直接访问外网,而本地电脑已有代理时,可通过SSH远程端口转发建立隧道。核心步骤是:确保本地代理可用,然后使用`ssh -fN -R 18080:127.0.0.1:7897 user@server`命令建立后台隧道,将服务器本地的18080端口转发到本地代理端口。成功后,在服务器设置HTTP_PROXY等环境变量指向127.0.0.1:1808...

服务器在内网或被限制访问外网,但本地电脑可以翻墙,希望让服务器通过本地网络访问外网。

典型场景:

最终实现的网络结构如下:

Server (127.0.0.1:18080)

        │ SSH RemoteForward

Mac (127.0.0.1:7897)


本地代理 / Clash / VPN


Internet

也就是说:

服务器访问 127.0.0.1:18080

→ SSH 隧道

→ Mac 127.0.0.1:7897

→ 本地代理

→ 外网


一、准备条件

需要满足两个前提:

1 本地电脑翻墙

我这里用的是 Clash Verge

本地 HTTP 代理端口是:

127.0.0.1:7897

测试方法:

curl -x <http://127.0.0.1:7897> <https://chatgpt.com> -I

如果看到:

HTTP/1.1 200 Connection established

说明代理是可用的。

如果没有成功,这一步必须先解决。


2 可以 SSH 登录服务器

例如:

# ip_path:port的格式,例如:
114.51.4.0:40022

登录用户:

user_name

二、核心原理:SSH RemoteForward

SSH 支持一种功能:

-R remote_port:local_ip:local_port

意思是:

服务器 remote_port

SSH 隧道

本地 local_ip:local_port

在我们的例子里:

-R 18080:127.0.0.1:7897
# 18080,7897都是人为预先规定好的,只要端口不冲突,就可以不变,这与服务器无关

意思是:

服务器 127.0.0.1:18080

SSH

Mac 127.0.0.1:7897

三、最简单可靠的做法(推荐)

直接在本地 Mac 上建立 SSH 隧道:

ssh -fN -p 40022 -R 18080:127.0.0.1:7897 user@server

参数解释:

-f   后台运行
-N   不执行远程命令
-R   远程端口转发

运行之后,这条 SSH 会在后台保持。

这样的一个SSH隧道的作用仅仅是确保端口相连

不太推荐的做法

最初被推荐在VSCode的config文件中,定义下面的内容

Host Server_Name
    HostName xx.x.x.xx
    Port xxx
    User xxxx
    RemoteForward 18080 127.0.0.1:7897

不过这样可能会遇到VSCode并没有按照设置的port与remoteforward方案来连接的情况,彻底关闭终端后可以重新开启服务,如果依旧出现问题的话还是建议利用上面的代码直接建立SSH隧道~


四、服务器测试代理是否成功

登录服务器后执行:

ss -lntp | grep 18080

如果成功应该看到:

127.0.0.1:18080 LISTEN

然后测试:

curl -v -x <http://127.0.0.1:18080> <https://chatgpt.com> -I

如果看到:

HTTP/1.1 200 Connection established

然后可能跟着:

HTTP/2 403
cf-mitigated: challenge

这是 Cloudflare challenge,是正常现象

说明代理已经成功。


五、服务器设置环境变量(非常重要)

很多程序不会读取 VSCode 的代理设置,而是读取环境变量。

建议在服务器执行:

export HTTP_PROXY=http://127.0.0.1:18080
export HTTPS_PROXY=http://127.0.0.1:18080
export ALL_PROXY=http://127.0.0.1:18080

如果确认正常,可以写入:

~/.bashrc

或者

~/.zshrc

六、VSCode 远程代理设置

如果使用 VSCode Remote SSH,需要在远端设置:

settings.json

加入:

{
  "http.proxy": "<http://127.0.0.1:18080>",
  "http.proxySupport": "on"
}

注意端口必须一致。


七、常见坑总结(这部分很重要)

整个过程中遇到了很多坑,这里全部记录一下。


坑一:服务器没有监听端口

最常见问题:

curl: Failed to connect to 127.0.0.1 port 18080

排查:

ss -lntp | grep 18080

如果为空,说明:

SSH RemoteForward 没建立

原因可能是:


坑二:VSCode 只是刷新,没有重建 SSH

很多人会做:

Reload Window

但 RemoteForward 只会在 建立 SSH 时生效

正确操作:

Remote-SSH: Close Remote Connection

然后重新连接。


坑三:SSH 隧道窗口关闭

如果你运行的是:

ssh -N -R ...

只要关闭这个终端:

RemoteForward 就消失

解决方案:

ssh -fN -R ...

后台运行。


坑四:端口写错

例如:

SSH 配置:

18080

VSCode 写:

18081

服务器 curl:

18091

这会导致各种莫名其妙的问题。

端口必须统一。


坑五:本地代理端口搞错

很多人以为 Clash 是:

7890
7891

但实际端口可能是:

33331
7897

检查方法:

lsof -i -P | grep LISTEN

坑六:代理不是 HTTP 代理

如果出现:

HTTP/1.1 404 Not Found

说明这个端口不是 HTTP proxy。

HTTP 代理必须返回:

HTTP/1.1 200 Connection established

坑七:tinyproxy 其实没必要

一开始尝试:

tinyproxy

但实际上:

只要本地代理支持 HTTP proxy,

tinyproxy 完全不需要。

直接:

RemoteForward -> 本地代理

更简单。


八、完整网络流程总结

最终网络结构:

Server
127.0.0.1:18080

      │ SSH RemoteForward

Mac
127.0.0.1:7897


Clash / VPN


Internet

服务器访问:

127.0.0.1:18080

就等价于:

Mac 7897

九、一个非常实用的小技巧

可以写一个脚本启动隧道:

#!/bin/bash

ssh -fN \\
-p 40022 \\
-R 18080:127.0.0.1:7897 \\
user@server

保存为:

ssh_proxy.sh

以后只需要:

bash ssh_proxy.sh

十、最终总结

要让服务器访问外网,本质只需要三件事:

1 本地电脑有代理

2 SSH RemoteForward

3 服务器走代理

核心命令:

ssh -fN -R 18080:127.0.0.1:7897 user@server

测试:

curl -x <http://127.0.0.1:18080> <https://chatgpt.com> -I

如果成功,服务器就能访问外网了。



Next
苹果live图