乐趣区

关于ssh:端口映射

端口映射

背景

  • 公网服务器上有些服务实际上没有必要间接裸露在公网端口,比方各种 dashboard,因为仅仅是本人查看即可,为了尽量避免端口裸露,从而多大被攻击面,尝试应用 ssh 端口映射实现跨防火墙的服务拜访
  • SSH 端口转发也称作 SSH 隧道,通过 SSH 登陆之后,在 SSH 客户端与 SSH 服务端之间建设了一个隧道,从而进行通信。SSH 隧道是十分平安的,因为 SSH 是通过加密传输数据的(SSH 全称为 Secure Shell)

分类

  • ssh 端口映射可分为三类:

    • 本地端口映射

      • 将发送到本地端口的申请,转发到指标端口,个别用于在本地平安的拜访放在公网服务器的一些私密服务,比方数据库服务,而不必在公网服务器的防火墙中关上该服务的端口
    • 近程端口映射

      • 将发送到近程端口的申请,转发到指标端口,个别用于做内网穿透,行将内网中的服务映射到公网服务器的某端口,从而实现从公网拜访内网的服务
    • 动静端口映射

      • 可用于迷信,应用近程主机作为 proxy,进行申请转发

autossh

  • 创立 SSH 隧道实际上应用 ssh 命令即可,然而该命令创立的隧道服务在网络稳定或者网络断开的状况下就会断开连接,很不稳固,很难用在生产环境,并且其对于 SSH 隧道的反对也并不欠缺,配置起来绝对繁琐。而 autossh 命令则是专门为构建 SSH 隧道构建的,反对对 SSH 连贯进行监控,反对主动重连,大大晋升 SSH 隧道的稳定性

实例

  • 这里以本地端口映射为例进行阐明,如果要实现其余类型的端口映射能够参考下边的链接进行尝试
  • 假如这样一个背景:

    我有一个 dashboard 服务部署在腾讯云的公网服务器 A,同时在我的内网开发环境中还有一台服务器 B。因为该 dashboard 服务仅仅是本人做监控用的,为了平安期间,没必要在腾讯云的防火墙设置中专门为该 dashboard 开一个端口进去,所以思考应用 SSH 端口映射。假如公网服务器 A 的 IP 是 IP_A,服务器 B 的 IP 是 IP_B,服务器 A 的用户名是 root,服务器 A 的 SSH 服务的端口就是默认的 22,目标是要把服务器 A 上监听在 60031 这个端口的服务映射到服务器 B 的 50031 端口

筹备工作

  • 对公网服务器 A 与内网服务器 B 对立做如下配置:

    # 编辑文件
    nano /etc/ssh/sshd_config
    # 增加下述配置
    GatewayPorts clientspecified
    # 重启 ssh 服务
    service sshd restart
  • 在内网服务器 B 中创立 SSH 秘钥对,如果有的话(~/.ssh/文件夹下),就不必创立了,能够间接用,若没有应用 ssh-keygen 命令创立,随后将服务器 B 的公钥 ~/.ssh/id_rsa.pub 的内容复制到公网服务器 A 的 authorized_keys 文件中(若没有,则创立一个,地位是~/.ssh/authorized_keys
  • 在服务器 B 上执行ssh root@IP_A -p 22,可能会有对话询问是否将服务器 A 增加到本地记录当中,键入 Y 确定即可,如果能胜利的通过 SSH 连贯到服务器 A,则筹备工作结束

部署端口映射

  • 博主自己比拟喜爱洁净的宿主机环境,因而间接应用 Docker 部署 autossh 服务,将该容器部署在服务器 B 上,实际上该容器将服务器 A 的端口映射到容器的某个端口,而后又能够通过 Docker 本身的端口映射,将其映射到宿主机的 50031 端口,应用的镜像是 autossh Docker Image
  • 在服务器 B 上应用 Docker Compose 构建服务,配置文件 autossh.yaml 如下:

    version: '3.7'
    
    services:
      
      ssh-local-forward:
        image: jnovack/autossh
        container_name: autossh-ssh-local-forward
        environment:
          - SSH_REMOTE_USER=root
          - SSH_REMOTE_HOST=IP_A
          - SSH_REMOTE_PORT=22
          - SSH_BIND_IP=0.0.0.0
          - SSH_TUNNEL_PORT=50031
          - SSH_TARGET_HOST=127.0.0.1
          - SSH_TARGET_PORT=60031
          - SSH_MODE=-L
        restart: always
        ports:
          - 50031:50031
        volumes:
          - /root/.ssh/id_rsa:/id_rsa
    • 替换 IP_A 的值
    • SSH_BIND_IP指定的实际上是要将服务器 A 的端口服务映射到服务器 B 的哪个网络接口上,个别就是 0.0.0.0 即全副接口
    • SSH_TARGET_HOST指的是将服务器 A 的哪个网络接口上的服务进行映射,个别是127.0.0.1,可依据场景适时更改
    • 留神 ports 指定了将容器的端口服务最终映射到了宿主机上,这样拜访起来更加不便些
    • volumes指定映射了服务器 B 上的私钥的地位,如果不是 root 用户,则灵便更改即可
  • 执行 docker-compose -f autossh.yaml up -d 即可构建 SSH 隧道,实际上执行的命令是autossh -M 0 -N -o StrictHostKeyChecking=no -o ServerAliveInterval=10 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes -t -t -L 0.0.0.0:50031:127.0.0.1:60031 -p 22 root@IP_A
  • 此时则能够通过拜访服务器 B 的 50031 端口来实现对服务器 A 上的 60031 端口的服务进行拜访,而不必再服务器 A 的防火墙凋谢 60031 端口

其余

  • 上面以纯命令行形式介绍其余类型的端口映射,如果要应用 Docker,间接参考其 DockerHub 页面,仿照着来即可

本地端口映射

  • 接续上边的背景,能够使主机 B 作为直达,最终实现通过与主机 B 同一内网的主机 C(IP 为 IP_C)的某端口拜访主机 A,只须要做下边的配置(主机 B 上执行)

    autossh -M 0 -N -o StrictHostKeyChecking=no -o ServerAliveInterval=10 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes -t -t -L IP_C:50031:127.0.0.1:60031 -p 22 root@IP_A
    • 当然,要实现设置主机 C 顺利 SSH 连贯到主机 A,参考前边的筹备工作局部
  • 同理的,能够通过以与主机 A 同一内网的服务器 D(公网 IP 为 IP_D)为直达,实现主机 A 到主机 B 的端口映射,假如主机 A 的内网 IP 是 IP_A_LAN

    autossh -M 0 -N -o StrictHostKeyChecking=no -o ServerAliveInterval=10 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes -t -t -L IP_C:50031:IP_A_LAN:60031 -p 22 root@IP_D
    • 当然,要实现设置主机 B 顺利 SSH 连贯到主机 D,参考前边的筹备工作局部

近程端口映射

  • 背景:

    没有公网 IP 的内网主机 B 部署了监听在 3000 端口的 web 服务,须要通过公网主机 A 去代理此服务,以将服务裸露到公网主机 A 的 4000 端口,供任意其余主机拜访

  • 筹备工作同理
  • 在内网主机 B 上执行

    autossh -N -f -M ${监听端口} -i /root/.ssh/id_rsa -R 0.0.0.0:4000:localhost:3000 root@IP_A -p 22
    • 监听端口用来执行对 SSH 隧道的监听,以实现隧道保活

      • autossh 会默认占用此端口以及此端口 + 1 的端口,留神不要有端口抵触
    • -f 示意后盾运行
    • -N 不执行近程命令,只进行端口转发,意思就是指进行端口转发而不接入近程 shell
    • -R 示意是近程端口映射(反向代理)区别于 - L 本地端口映射(正向代理)
    • 一般来说验证 autossh 有没有失效的办法就是查看过程中有没有对应的 ssh 命令,ps -aux | grep ssh看看除了 autossh 之外,有没有主动执行其余的 ssh 命令,如果有的话,就是执行胜利了,如果失败能够尝试更换 -M 后的端口
    • 仿照上一节的本地端口映射的补充内容,这里也能够灵便设置

动静端口映射

  • 筹备工作同理
  • 对于本地端口转发和近程端口转发,都存在隧道两端的服务器的两个一一对应的端口,而动静端口转发则只是绑定了一个本地端口,而指标地址: 指标端口则是不固定的,由发动的申请决定
  • 背景:

    能够将在本地主机 B 发动的申请,转发到近程主机 A,而由 A 去真正地发动申请(对主机 A 的本机服务发动申请,或者是其余 A 能拜访到的服务)

  • 在内网主机 B 上执行:

    autossh -N -f -M ${监听端口} -i /root/.ssh/id_rsa -D IP_B:2000 root@IP_A -p 22
    • 2000 端口能够认为是 B 上的代理服务的端口
    • IP_B 是 B 的内网 IP,能够认为是 B 上的代理服务的地址
    • IP_A 是 A 的公网 IP
  • 内网 B 上利用发动的申请,须要由 Socket 代理 (Socket Proxy) 转发到内网代理端口(即上边的 2000)。以 Firefox 浏览器为例,配置 Socket 代理须要找到首选项 → 高级 → 网络 → 连贯 → 设置

    • Firefox 浏览器发动的申请都会转发到 2000 端口,而后通过 SSH 转发到真正地申请地址。如果服务器 A 上有一个 Node.js 服务,则在 Firefox 中拜访 localhost:${Node.js 服务端口}即能够拜访该服务

参考

  • autossh
  • autossh Docker Image
退出移动版