SSH "端口三剑客"(-L、-R、-D参数的妙用)
0. 前言
- 在刚开始学习使用 Linux 的时候,大家几乎都是使用
OpenSSH的ssh命令登录到服务器的吧~ - 在我使用 Linux 学习、开发,以及日常逛知乎的过程中,有缘接触到了 SSH "端口三剑客" 的使用,在此分享给大家。
1. 远程端口转发到本地(参数 -L)
有的时候在服务器上开启了一个端口服务(例如:Jupyter Lab),可是只能通过服务器上的
127.0.0.1或localhost,才能访问。$ jupyter lab To access the server, open this file in a browser: file:/home/asparagus/.local/share/jupyter/runtime/jpserver-15584-open.html Or copy and paste one of these URLs: http://localhost:8888/lab?token=97615e2aa2e9841decfe56e87419a11202c2ccb5a2e8f340 http://127.0.0.1:8888/lab?token=97615e2aa2e9841decfe56e87419a11202c2ccb5a2e8f340总不能为这碟醋而包个饺子,在远程服务器上装个桌面环境( Gnome、KDE 等)或者窗口管理器( i3wm、sway、niri 等),以及笨重的浏览器、VNC服务吧!毕竟可能没有
root权限或者服务器资源有限。此外,从安全的角度考虑,如果这些服务的端口直接暴露到公网上(0.0.0.0),确实是方便我们访问了,但有潜在的风险——总有些吃饱了撑的人会挂个脚本,日夜午休爆破你的端口。
聪明的做法则是把对应端口通过
ssh安全的转发到本地主机的127.0.0.1或localhost上,通过本地主机的浏览器来访问:# 推荐额外添加 -N 与 -T 参数,这样就不会进入ssh的交互界面了 # 注意:需要保持当前终端一直开启,不要关闭 # 在本地电脑上: ssh -NTL 127.0.0.1:8888:127.0.0.1:8888 远程服务器上的账户名@远程服务器的IP # 语法:-L [本地监听地址:]本地端口:远端地址:远端端口 # 第一个127.0.0.1和8888是你本地电脑的环回ip与端口,如果端口冲突可以换成别的 # 第二个127.0.0.1和8888是你远程服务器的环回ip与端口,根据你想转发的具体服务来调整(这里即我远程运行的 Jupyterlab 服务)之后在你的本地电脑上打开浏览器,输入之前对应的网址(例如我的:
http://localhost:8888/lab?token=97615e2aa2e9841decfe56e87419a11202c2ccb5a2e8f340),就可以安全访问啦。
2. 本地端口转发到远程(参数 -R)
既然能把端口从远程服务器转发到本地主机,那反过来是不是也可以呢?(同样也是为了安全考虑)
记得我当初开发网站的时候,由于囊中羞涩,使用的云服务器都是很小的配置,根本跑不了完整的生信流程,更不用说在此基础上开发类似于
Galaxy那样的在线分析平台了。毕竟给我的网站上域名怎么也得有个公网 IP 吧(
Cloudflare Tunnel除外)。于是我脑中灵机一动,可不可以在本地服务器运行具体的生信分析流程,远程服务器只作为公网上的“传话筒”,将用户通过域名访问的相关操作,传递到性能较好但没有公网 IP 的本地服务器上呢?
答案当然是肯定的,之前准备计算机设计比赛时我就用到了
-R这个参数,将本地服务器上的Flask后端服务转发到远程服务器进行访问。# 推荐额外添加 -N 与 -T 参数,这样就不会进入ssh的交互界面了 # 同样的,也要保持当前终端一直开启,不要关闭 # 在本地电脑上: ssh -NTR 127.0.0.1:8000:127.0.0.1:8000 远程服务器上的账户名@远程服务器的IP # 语法:-R [远程监听地址:]远程端口:本地地址:本地端口 # 第一个127.0.0.1和8000是你远程服务器的环回ip与端口,如果端口冲突可以换成别的 # 第二个127.0.0.1和8000是你本地服务器的环回ip与端口,根据你想转发的具体服务来调整(这里即我本地运行的 Flask 后端服务)然后在远程服务器上就可以访问本地的
Flask了,最终使用NGINX给它上了域名,实现安全的公网访问。
3. "动态转发端口"(参数 -D)
有时候克隆
Github仓库真的慢,即便使用第三方镜像,加速效果也不一定稳定。还有下载一些服务器位于国外的文件,例如
NCBI SRA的文件大多在亚马逊云上,国内下载速度也很感人。别急,
ssh"端口三剑客" 的最后一位可以来帮忙!-D参数可以在本地主机开一个socks4/5端口(这不相当于是个梯子嘛),可以相对提高我们本地主机对国外网站的访问速度。前提是需要租一台国外的服务器,装有
openssh并且启用了sshd服务。具体操作如下:
3.1 配置代理端口
# 推荐额外添加 -N 与 -T 参数,这样就不会进入ssh的交互界面了 # 同样的,也要保持当前终端一直开启,不要关闭 # 在本地主机上: ssh -NTD 1080 远程服务器上的账户名@远程服务器的IP
3.2 安装
proxychains接下来,该如何使用上面的
socks5代理呢?虽然像
curl、git等工具本身就支持socks5代理,但还是有些软件不支持( 如wget ),或者配置起来比较麻烦,所以我这里通过proxychains软件统一一下,使用时只需要在相关命令最前面添加proxychains及对应参数即可。根据你的情况,选择下列其中一种方法:
3.2.1 使用
conda/mamba安装假如你已经装了
anaconda/miniconda/miniforge/mamba/micromamba,可以直接去conda-forge频道安装。# 安装步骤根据你的情况,三选一即可 ## anaconda / miniconda conda install -c conda-forge proxychains-ng ## miniforge / mamba mamba install -c conda-forge proxychains-ng ## micromamba micromamba install -c conda-forge proxychains-ng # 编辑配置文件 echo -e "[ProxyList]\nsocks5 127.0.0.1 1080" > ~/.local/proxychains.conf # 测试(-q 参数简化相关输出) proxychains4 -q -f ~/.local/proxychains.conf curl -s https://api.ip.sb/geoip # 检查输出,是否是你远程服务器的地区和ip # 如果是,则说明成功啦 # 如果还是国内ip,则需要仔细排错一下咯
3.2.2 编译安装
- 假如你没有安装上述虚拟环境包管理器,可以通过编译安装(需要 gcc、make等工具链)。
# 这里使用 kkgithub 镜像加速下载源代码 wget -c https://kkgithub.com/rofl0r/proxychains-ng/releases/download/v4.17/proxychains-ng-4.17.tar.xz # 解压后进入文件夹 tar xvf proxychains-ng-4.17.tar.xz cd proxychains-ng-4.17 # 最终将 proxychains 安装到 $HOME/.local/bin 路径 ./configure --prefix=$HOME/.local # 编译并安装 make && make install # 编辑配置文件 echo -e "[ProxyList]\nsocks5 127.0.0.1 1080" > ~/.local/proxychains.conf # 测试(-q 参数简化相关输出) proxychains4 -q -f ~/.local/proxychains.conf curl -s https://api.ip.sb/geoip # 检查输出,是否是你远程服务器的地区和ip # 如果是,则说明成功啦 # 如果还是国内ip,则需要仔细排错一下咯
3.2.3 系统级包管理器安装
假如你有
root权限,想装完让大家一起用的话:# 根据你的本地服务器发行版自行选择对应包管理器 ## Debian系 sudo apt install proxychains4 ## Red Hat系 sudo yum install proxychains-ng # CentOS sudo dnf install proxychains-ng # rhel、fedora等 ## 其他的发行版请自行上网搜索,注意包名可能略有不同 # 编辑配置文件 sudo vim /etc/proxychains.conf # 将最后一行修改成 socks5 127.0.0.1 1080 # 测试(-q 参数简化相关输出) proxychains4 -q curl -s https://api.ip.sb/geoip # 检查输出,是否是你远程服务器的地区和ip # 如果是,则说明成功啦 # 如果还是国内ip,则需要仔细排错一下咯
3.3 使用
socks5代理使用时只需要在相关命令最前面添加
proxychains及对应参数即可。# -q 参数简化相关输出, -f 指定 proxychains 的配置文件 ## git clone proxychains4 -q -f ~/.local/proxychains.conf git clone https://github.com/vim/vim ## wget proxychains4 -q -f ~/.local/proxychains.conf wget https://github.com/vim/vim/archive/refs/heads/master.zip当然,为了方便使用,可以添加一个
alias到你的 shell 里面。# 以 bash 为例 echo "alias pc='proxychains4 -q -f ~/.local/proxychains.conf'" >> ~/.bashrc source ~/.bashrc # 这样以后使用起来就方便啦~ pc git clone https://github.com/vim/vim pc wget https://github.com/vim/vim/archive/refs/heads/master.zip
4. 尾声
当然,上述的 "三剑客" 其实局限性也很大,例如只能转发 TCP 端口、对 UDP 端口无效,需要前台一直挂着,不好配置常驻服务等。因此只适合临时使用。
日常开发中,我还是喜欢直接用
VSCodeRemote SSH 插件中的 Port Forwarding,免去了很多麻烦(端口冲突等)。实际的生产环境中,
openssh的-L与-R参数可以被端口转发工具(如frp等)或虚拟组网工具(如wireguard等)替代,以实现更加稳定的端口转发服务。而-D参数的替代品就不再展开讲了,毕竟懂得都懂,嘻嘻。同样的,
sshd服务本身的端口也需要注意防护攻击:比如禁用root登录、仅允许使用密钥登录、部署fail2ban服务等,从而加强公网服务器自身的安全等级。附录:OpenSSH 官方手册