端口映射

背景

  • 公网服务器上有些服务实际上没有必要间接裸露在公网端口,比方各种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