32、【Ubuntu】【远程开发】内网穿透:远程主机连接

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除

背景

上篇 blog
【Ubuntu】【远程开发】内网穿透:反向隧道建立(三)

分析了 SSH 反向隧道的建立,下面继续分析

内网穿透

SSH 反向隧道建立之后,用户先用 ed25519 算法在本地生成公私钥

bash 复制代码
ssh-keygen -t ed25519 -C "your_email@example.com"

然后将公钥先上传到内网服务器

这里可以先用局域网,上传好公钥,上传方法之前 blog 【Ubuntu】【远程开发】内网穿透:SSH 建立连接 介绍过了,输入命令

bash 复制代码
echo "公钥信息" >> ~/.ssh/authorized_keys

假设现在是 Windows 电脑,打开 PowerShell,输入

bash 复制代码
ssh -p ServerPort ClientUser@ServerIp

连接云服务器上已经建立反向隧道的端口即可

可以看到,用另一台远程主机通过云服务器,成功连接上了内网的电脑 ,注意,这里的用户名是内网服务器的用户名,不是云服务器上的用户名

至此,内网穿透已成功实现

通过设置云服务器防火墙,可以在不用的时候,将该端口禁用掉,防止受到攻击

如果在远程主机的 IP 固定,也可以对来源 IP 进行限制,这样就可以不用 0.0.0.0 开放所有 IP 访问了

OK,内网穿透已经实现了,下面再聊点别的,比如稳定性,在 SSH 反向隧道建立后,常态运行过程中,可能因为各种原因出现断联,比如

  • 网络中断:比如 WiFi,网线断开,ISP 网络运营商的 NAT 超时,防火墙切断空闲连接等
  • 服务器主动关闭连接:比如长时间未响应,重启 SSH 服务,OOM(Out Of Memory 内存耗尽)杀死进程等
  • 客户端本地异常:比如休眠,关机,或者不小心关闭对应的进程等

此时 SSH 会话就会断联,无法继续通信,如果人在外地,不能及时恢复的话,就很麻烦,而且如果是假死状态,就更麻烦(对自动化脚本来说) ,这里的假死状态指的是 连接状态未更新,用户误以为还通着,其实早已断了,SSH 一些假死的典型表现比如

  • 终端卡住,按回车没反应 发的命令根本没传到服务器

  • ctrl c 无效,因为中断信号都发不出去

  • 然后过了几分钟后突然显示 send disconnect: Broken pipeTCP 最终超时 ,SSH 这才意识到连接已断

  • 如果开启了 tmux 会话,tmux attach 的时候会发现会话(terminal multiplexers 终端复用器)无法恢复,实际上早就断了,只是客户端没检测到

  • 上面的 tmux 再多说两嘴,对于普通的 Shell 会话,一旦 SSH 断开,Shell 会收到 SIGHUP 信号,自动退出,并杀死由它启动的所有子进程,而 tmux 能隔离这个信号,让程序不受 SSH 断开影响

  • tmux 可以在一个 SSH 连接里创建多个虚拟终端就像开了多个标签页 ,即使后面 SSH 断开,里面的程序仍在后台运行,重新连接 SSH,tmux 可以恢复回原来的会话,能看到程序还在跑,输出还在继续

所以可以看到,SSH 连接在表面上看起来还活着(终端没报错,光标还能闪),但实际上底层网络已经断开,任何输入的命令都不会被服务器收到,也不会有任何响应 ,给人的感觉就像卡住了一样

这种假死状态主要是因为 TCP 协议本身没有自动探测机制(除非开启 TCP keepalive)

  • 正常断开:服务器发送 FIN 包通知结束,客户端就知道了连接关闭
  • 异常断开 :比如断电,拔网线,NAT 表老化,就不会有任何通知 ,但此时客户端仍认为连接有效直到尝试发数据 失败后触发重传,直到超时失败(可能几十秒甚至几分钟),或者系统 TCP keepalive 超时(Linux 默认大约要 2 小时)

所以,在没有应用层保活的情况下,SSH 对这种静默断开毫无感知能力


OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog
【Ubuntu】【远程开发】内网穿透:连接可靠性(一)

相关推荐
yolo_guo2 小时前
WSL2 安装 centos6.9 子系统
linux
p66666666682 小时前
【☀Linux驱动开发笔记☀】新字符设备驱动开发_02
linux·嵌入式硬件·学习
大聪明-PLUS2 小时前
在 Linux 上使用实时调度策略运行应用程序
linux·嵌入式·arm·smarc
Awkwardx2 小时前
Linux网络编程—应用层自定义协议与序列化
linux·网络
java_logo2 小时前
Kubernetes Dashboard Docker 容器化部署指南
运维·mysql·docker·云原生·容器·kubernetes·php
编织幻境的妖2 小时前
Docker底层工作原理
运维·docker·容器
TDengine (老段)3 小时前
TDengine IDMP 赋能新能源:光伏电站智能运维实践
大数据·运维·数据库·物联网·时序数据库·tdengine·涛思数据
小武~3 小时前
#嵌入式Linux电源管理实战:深入解析CPU调频governor原理与优化
linux
gcfer3 小时前
Docker 介绍和常用命令
运维·docker·容器