惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
Cisco Talos Blog
Cisco Talos Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
博客园 - 三生石上(FineUI控件)
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
D
Docker
S
SegmentFault 最新的问题
博客园 - 聂微东
美团技术团队
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
GbyAI
GbyAI
L
LangChain Blog
Vercel News
Vercel News
博客园 - 叶小钗
MongoDB | Blog
MongoDB | Blog
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
Engineering at Meta
Engineering at Meta
T
Threat Research - Cisco Blogs
T
Threatpost
Scott Helme
Scott Helme
T
Tailwind CSS Blog
Latest news
Latest news
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
The Register - Security
The Register - Security
罗磊的独立博客
P
Proofpoint News Feed
腾讯CDC
S
Schneier on Security
雷峰网
雷峰网
A
About on SuperTechFans
T
Tenable Blog
F
Full Disclosure
Cyberwarzone
Cyberwarzone
博客园_首页
有赞技术团队
有赞技术团队
K
Kaspersky official blog

文章列表

游戏玩后感:ReLief:献给亲爱的你 我的周边(谷子)分享 游戏玩后感:Kanon 简谱:致真实的你 《Rust中常见的有关生命周期的误解》学习笔记 简谱:StarMap 简谱:かく咲きたらばいと恋ひめやも 简谱:东风 简谱:无法诉说的思念 简谱:Girlish 游戏玩后感:时钟机关的Layline 简谱:风之琶音 简谱:星空的记忆 简谱:因为遇见了你 简谱:月童 番茄简谱脚本转调器 游戏玩后感:青空下的约定:Refine 游戏玩后感:在这苍穹展翅 书籍读后感:控制论与科学方法论 游戏玩后感:恋爱表达式 游戏玩后感:樱之诗 MLIR-tutorial学习笔记 游戏玩后感:潜伏之赤途 游戏玩后感:纯爱咖啡厅:帕露菲重制版 游戏玩后感:智以泪聚 游戏玩后感:初雪樱 游戏玩后感:告别回忆:从今以后 游戏玩后感:梦灯花 游戏玩后感:金辉恋曲四重奏 游戏玩后感:五彩斑斓的世界 昇腾310P使用记录 游戏玩后感:AIR 游戏玩后感:弹丸论破 游戏玩后感:流景之海的艾佩莉亚 Xilinx_HLS上板过程记录 游戏玩后感:告别回忆2 游戏玩后感:恋爱绮谭 Faiss和Rapidsai_Raft使用记录 游戏玩后感:近月少女的礼仪 游戏玩后感:樱色之云,绯色之恋 游戏玩后感:幸运草的约定 游戏玩后感:星之梦、候鸟和丸子与银河龙 游戏玩后感:白色相簿2 Windows上使用VTune分析PyTorchExtension调用的Cpp程序 SpinalHDL上板过程记录 游戏玩后感:仰望夜空的星辰 最简单的算卦方法之一:梅花易数法 游戏玩后感:苍之彼方的四重奏 krkr引擎解包工具介绍 自定义CUDA实现PyTorch算子的四种简单方法 游戏玩后感:星空的记忆 游戏玩后感:9nine 游戏玩后感:AtriMyDearMoments 游戏玩后感:极限脱出 游戏玩后感:魔女的夜宴 动漫观后感:向山进发 flv重封装H264、AAC流 游戏玩后感:LittleBustersEX 游戏玩后感:SummerPockets 游戏玩后感:逆转裁判 动漫观后感:吹响吧上低音号 使用OpenCV对图片进行特征点检测和匹配 git基本操作
SSH实现多跳代理
VnYzm · 2023-04-13 · via

背景

我们实验室有两台服务器,其中一台无法从外网访问,另一台设置了内网穿透。我平常在无法从外网访问的那台服务器上做实验,所以如果在实验室外要连接那台服务器就需要将设置了内网穿透的服务器作为跳板,通过两次ssh登进实验服务器。

最近我的实验需要联网下载包,但是服务器要联网需通过登录认证服务网页进行认证,而服务器又没有安装远程桌面,直接通过命令行访问认证网页实在是力不从心。所以我需要想办法设置代理,使得我可以通过自己电脑上的浏览器通过实验服务器访问认证网页,从而登录上网。

总结一下需求,就是网络中有A、B、C、D四个节点,其中A和B互联,B和C互联,C和D互联,如何设置使得A能访问D。

方法

考虑简单情况,如果B和D是互联的,那么就可以直接通过ssh的Socks代理实现功能,具体步骤如下:

  1. 在A运行:ssh -N -D 127.0.0.1:Aport B。其中Aport可以是A上任意闲置的端口。
  2. 在A中打开浏览器,设置浏览器的代理为socks5://127.0.0.1:Aport,然后输入D的网址,即可访问认证网页。

实际上,相当于A对D的请求被ssh代理转发到B上,由B的sshd进程访问D。所以如果B服务器要上网,通过这种方法在D上认证后能够上网的就是B。那么如何将A对D的请求转发到C上,由C访问D呢?

失败方法

我一开始考虑的方法是利用ssh的端口转发功能,端口转发实现的是将远程服务器的端口映射到本地端口。这么说是不是很抽象,然而大部分博客就是这样说的,能看懂就见鬼了。以我的需求做例子,在B上运行命令:ssh -L Bport:Dhostname:Dport C,其中Bport可以是B上任意闲置的端口,实现的功能就是可以通过访问Bport端口透过C访问D了。那么理论上我就可以通过前面所说的Socks代理方法用A访问D:

  1. 在A运行:ssh -N -D 127.0.0.1:Aport B。其中Aport可以是A上任意闲置的端口。
  2. 在A中打开浏览器,设置浏览器的代理为socks5://127.0.0.1:Aport,然后输入https://127.0.0.1:Bport,通过B代理透过C访问D。

为了测试,我在B上运行curl -I https://127.0.0.1:Bport,连是能连,但返回了证书错误,说明如果验证网页是http,方法应该是可行的。可惜认证网页是https,让我不得不去寻找其他方法。

顺带一提,ssh的端口转发功能分为两种,一种是本地端口转发,一种是远程端口转发,前面使用参数-L的方法是本地端口映射,如果要使用远程端口映射,则在C上运行命令ssh -R Bport:Dhostname:Dport B,其中Bport可以是B上任意闲置的端口,实现的功能和本地端口映射完全等价,不过本地端口转发是B上的ssh负责监听,转发给C上的sshd负责请求;远程端口转发是B上的sshd负责监听,转发给C上的ssh负责请求,ssh和sshd互换了身份,当然对于我的需求,两种方法都不满足。

成功方法

我在网上搜相关资料的时候,意外搜到一个给ssh本身添加代理的方法,顿时有了灵感。如果我能通过某种方法,使A能够直连到C,这样我就可以将C作为Socks5代理连到D了。那么如何使A直连到C呢?给ssh本身添加代理就是解决方案!具体步骤如下:

  1. 在A运行:ssh -N -D 127.0.0.1:Aport1 B,其中Aport1可以是A上任意闲置的端口。
  2. 在A运行:ssh -o ProxyCommand='C:\Program Files\Git\mingw64\bin\connect.exe -S 127.0.0.1:Aport1 %h %p' -N -D 127.0.0.1:Aport2 C,其中Aport2可以是A上任意和Aport1不一样的闲置端口。
  3. 在A中打开浏览器,设置浏览器的代理为socks5://127.0.0.1:Aport2,然后输入D的网址,即可访问认证网页。

注意A是Windows系统,所以给ssh添加代理的方法是使用connect.exe,Linux下使用的是Netcat,网上有很多相关资料。另外就是这个connect.exe似乎是Git自带的一个程序,我刚好电脑里有Git就用上了,不知道有没有别的办法。

这个方法的意思是先建立一个B服务器的代理,然后建立一个通过B代理连接C服务器的代理,再通过C代理连接D。从A出发的对D的请求,先通过第二条ssh指令转变为往C发送,而往C发送的请求通过第一条ssh指令转变为往B发送,B的sshd收到以后往C发送,C的sshd收到以后往D发送,就实现了功能。

扩展

基于该方法,不难将其扩展到任意跳服务器的代理。比如将我需求中的两跳服务器改为三跳,即有A、B、C、D、E五个节点,A和B互联,B和C互联,C和D互联,D和E互联,怎么从A连到E。参考前面方法,只需要在A执行三个ssh代理命令即可:

ssh -p Bport -N -D 127.0.0.1:Aport1 B
ssh -o ProxyCommand='C:\Program Files\Git\mingw64\bin\connect.exe -S 127.0.0.1:Aport1 %h %p' -N -D 127.0.0.1:Aport2 C
ssh -o ProxyCommand='C:\Program Files\Git\mingw64\bin\connect.exe -S 127.0.0.1:Aport2 %h %p' -N -D 127.0.0.1:Aport3 D

三条命令在不同的命令行窗口下执行。用浏览器设置Socks5代理端口为Aport3,就能访问E了。再多跳数也是如此,跳数多少就执行多少条ssh代理命令。