Skip to content

SSH "端口三剑客"(-L、-R、-D参数的妙用)

约 2346 字大约 8 分钟

Linuxopensshsshproxy

2026-01-01

0. 前言

  • 在刚开始学习使用 Linux 的时候,大家几乎都是使用 OpenSSHssh 命令登录到服务器的吧~
  • 在我使用 Linux 学习、开发,以及日常逛知乎的过程中,有缘接触到了 SSH "端口三剑客" 的使用,在此分享给大家。

1. 远程端口转发到本地(参数 -L

  • 有的时候在服务器上开启了一个端口服务(例如:Jupyter Lab),可是只能通过服务器上的 127.0.0.1localhost,才能访问。

    $ 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.1localhost 上,通过本地主机的浏览器来访问:

    # 推荐额外添加 -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),就可以安全访问啦。

    ssh_forwarding_jupyterlab

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 代理呢?

    • 虽然像 curlgit 等工具本身就支持 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 端口无效,需要前台一直挂着,不好配置常驻服务等。因此只适合临时使用。

  • 日常开发中,我还是喜欢直接用 VSCode Remote SSH 插件中的 Port Forwarding,免去了很多麻烦(端口冲突等)。

  • 实际的生产环境中,openssh-L-R 参数可以被端口转发工具(如 frp 等)或虚拟组网工具(如 wireguard 等)替代,以实现更加稳定的端口转发服务。而 -D 参数的替代品就不再展开讲了,毕竟懂得都懂,嘻嘻。

  • 同样的,sshd 服务本身的端口也需要注意防护攻击:比如禁用 root 登录、仅允许使用密钥登录、部署 fail2ban 服务等,从而加强公网服务器自身的安全等级。

  • 附录:OpenSSH 官方手册