ssh妙用
虽然SSH代理本身是高度加密的,但是防火墙能识别出协议是ssh,如果你用它来浏览网页或看视频,会产生长时间、高…
ssh端口转发(用于设置代理)
ssh -D [本地监听IP]:[本地端口] [用户名]@[远程服务器IP]作用: 在本地建立一个 SOCKS 代理服务器。
动态转发: 与固定端口转发(只能访问特定 IP 和端口)不同,“动态”意味着你可以通过这个隧道访问远程服务器能触达的任何地址。
虽然SSH代理本身是高度加密的,但是防火墙能识别出协议是ssh,如果你用它来浏览网页或看视频,会产生长时间、高带宽的 SSH 流量。这种“不正常”的行为很容易触发防火墙的封锁。所以如果为了安全需要,最好配合stunnel 进行的加密隧道传输。
严格来说,这通常被归类为 加密代理(Encrypted Proxy) 而非传统意义上的 VPN,但在广义的“科学上网”语境下,它们常被当作 VPN 的替代方案。
SSH 单独使用: 流量特征 = [TCP] -> [SSH 加密数据](容易被识别)。
SSH + Stunnel: 流量特征 = [TCP] -> [TLS/SSL 握手] -> [看似 HTTPS 的加密数据]。
Windows 批处理脚本 (Auto-Reconnect)
你可以创建一个
.bat文件(例如ssh_proxy.bat),将以下代码复制进去。即使连接断开,它也会每隔 30 秒自动尝试重新连接(使用 SSH 密钥对登录!):@echo off :loop echo [%date% %time%] 正在尝试建立 SSH 隧道... :: 如果你已经配置了密钥登录(推荐): ssh -D 127.0.0.1:18080 -N -o ServerAliveInterval=30 -o ServerAliveCountMax=3 root@google.cogrise.top (如果在config文件配置了其他的参数) ssh -N google.cogrise.top :: 如果连接断开,程序会执行到这里 echo [%date% %time%] 连接已断开或失败,30秒后重试... timeout /t 30 goto loop
-o ServerAliveInterval=30: 每隔 30 秒向服务器发送一个“心跳”包。
-o ServerAliveCountMax=3: 如果连续 3 次没收到回应,才认为连接断开。可以设置在本机
config文件里面Host google.cogrise.top User root Port 22 ServerAliveInterval 30 ServerAliveCountMax 3 DynamicForward 127.0.0.1:180801. 默认行为:静默等待
ServerAliveInterval: 默认值是 0。
- 这意味着客户端永远不会主动向服务器发送“心跳”包。
ServerAliveCountMax: 默认值通常是 3。
- 但因为 Interval 是 0,这个计数器实际上处于失效状态。
不设置会导致什么后果?
A. 被防火墙/路由器踢掉(死连接)
这是最常见的情况。很多网络设备(如家用路由器、公司防火墙或云服务商的负载均衡器)为了节省资源,会自动切断长时间没有数据传输的 TCP 连接。
B. 无法及时察觉断线
如果远程服务器意外重启或网络瞬间中断:
现象: SSH 客户端会卡在那里,既不报错也不退出,可能要等几十分钟(触发 TCP 自身的 KeepAlive 超时)才会提示
Connection timed out。
附上配置密钥对登录的全过程:
1. 在本地 Windows 生成密钥对
在你的 C:\Users\maluyao 路径下的命令行执行以下命令:
ssh-keygen -t ed25519-t ed25519: 这是目前最推荐的算法,比传统的 RSA 更快且更安全。
按回车确认: 提示保存路径和密码(Passphrase)时,全部直接按回车(不设置密码,这样重连时才不需要人工干预)。
生成结果: 你会在 C:\Users\maluyao\.ssh\ 文件夹下看到两个文件:
id_ed25519: 你的私钥(绝对不能给别人)。id_ed25519.pub: 你的公钥。
2. 将公钥上传到远程服务器
你需要把公钥的内容告诉服务器,以便它能识别你的电脑。
复制公钥内容: 用记事本打开 C:\Users\maluyao\.ssh\id_ed25519.pub,复制里面那串以 ssh-ed25519 开头的长字符串。
登录服务器并写入: 先最后一次手动输入密码登录到你的 Ubuntu 服务器,然后执行以下命令:
# 创建 .ssh 目录(如果不存在)
mkdir -p ~/.ssh
# 将公钥写入授权文件
echo "这里粘贴你刚才复制的公钥内容" >> ~/.ssh/authorized_keys
# 设置权限(非常重要,权限不对会导致无法登陆)
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys3. 修改本地 config 文件(终极优化)
现在你可以把所有的连接参数固化到 C:\Users\maluyao\.ssh\config 文件中:
Host myproxy
HostName google.cogrise.top
User root
Port 22
# 自动重连心跳设置
ServerAliveInterval 30
ServerAliveCountMax 3
# 密钥路径
IdentityFile ~/.ssh/id_ed25519
# 自动开启动态代理
DynamicForward 127.0.0.1:180804. 验证效果
现在,你在命令行只需要输入:
ssh -N myproxy它将不再询问密码,直接建立隧道。
Stunnel (TLS/SSL Tunnel)
用它来配合 SSH,主要是为了解决 SSH 流量特征过于明显的问题:
流量伪装: Stunnel 能够将任何 TCP 流量(比如 SSH 流量)封装在 标准的 TLS/SSL 隧道 中。
混淆: 这样在网络防火墙看来,你的流量就像是在访问一个普通的 HTTPS 网站,从而躲避对 SSH 协议的深度数据包检测(DPI)。
要使用 Stunnel 来给 SSH 隧道穿上“HTTPS 伪装衣”,你需要分别在服务端(VPS)和客户端(你的电脑)上进行配置。
第一步:服务端配置
1、安装 Stunnel:
# Ubuntu/Debian
sudo apt install stunnel4
# CentOS
sudo yum install stunnel2、生成 SSL 证书: Stunnel 需要证书来加密。为了方便,可以生成自签名证书:
openssl req -new -x509 -days 3650 -nodes -out /etc/stunnel/stunnel.pem -keyout /etc/stunnel/stunnel.pem3、创建配置文件:
新建并编辑 /etc/stunnel/stunnel.conf:
cert = /etc/stunnel/stunnel.pem
setuid = stunnel4
setgid = stunnel4
pid = /var/run/stunnel4/stunnel.pid
[ssh]
accept = 443
connect = 127.0.0.1:22
* accept = 443: Stunnel 监听的对外端口(伪装成 HTTPS)。
* connect = 127.0.0.1:22: 收到流量后转发给本地的 SSH 服务。4、启动服务:
sudo systemctl start stunnel4第二步:客户端配置
如果你用的是 Windows,可以去官网下载 Stunnel 安装包;macOS 可以使用 brew install stunnel。
1、编辑客户端配置文件 (stunnel.conf):
client = yes
[ssh]
accept = 127.0.0.1:10000
connect = [你的服务器IP]:443
* accept = 127.0.0.1:10000: 在你本地机器上开一个“入口”端口。
* connect = [你的服务器IP]:443: 连接到服务器上 Stunnel 监听的 443 端口。2、启动客户端 Stunnel。
第三步:通过“隧道中的隧道”建立 SSH 代理
现在,你的本地端口 10000 已经通过 TLS 加密直连到了服务器的 SSH 服务。你只需要把之前的 SSH 命令目标改为本地的这个“入口”即可:
ssh -D 1080 -N -f -p 10000 user@127.0.0.1为什么是 127.0.0.1? 因为此时本地的 10000 端口就等同于服务器的 SSH 端口。流量路径如下:
- 你的浏览器 ->
SOCKS5: 1080 - SSH 客户端 -> 转发到本地
10000 - Stunnel 客户端 -> 将数据包装成 TLS (HTTPS) -> 发往服务器
443 - Stunnel 服务端 -> 解开 TLS -> 发往服务器本地
22(SSH)
ssh本地转发
ssh -L [本地端口]:[目标IP]:[目标端口] user@server作用: 把远程服务器上的某个端口,“映射”到你本地电脑的某个端口。
场景: 比如远程服务器(内网)里跑着一个数据库(端口 3306),你的电脑连不上。你可以通过 SSH 把它映射到你本地的 3306。
原理: 访问本地 localhost:3306 = 访问远程 server:3306。
ssh -L [本地绑定地址:]本地端口:目标地址:目标端口 用户名@SSH服务器当你使用SSH密钥来连接远程服务器时,使用-i参数指定
-i /path/to/key.pem只想做端口转发,不需要进入vps,在后面加上-N参数
SSH 远程转发
ssh -R [服务器端口]:[目标IP]:[目标端口] user@server作用: 把你本地的某个端口,“反向映射”到远程服务器的某个端口。
场景: 内网穿透。比如你在寝室(内网)电脑跑了一个网站,想让身在外地的朋友通过你的服务器 IP 访问到你这台电脑。
你必须在 VPS 的 /etc/ssh/sshd_config 中控制哪些用户允许反向隧道:
# 确保以下配置开启
GatewayPorts yes
AllowTcpForwarding yes重新启动 SSH 服务:
sudo systemctl restart sshd调试
检查端口+kill进程

SSH 长时间空闲被踢
ssh -N -R 8868:localhost:8868 -o ServerAliveInterval=60 root@aliyun.maluyao.top如果本机没有开ipv6会出现问题,因为Windows主机优先把localhost解析为ipv6地址
Windows 上
localhost默认优先解析为 IPv6(::1), 而你的 Nginx 只监听了 IPv4(127.0.0.1), SSH 反向隧道实际连到了::1:443,结果直接被系统关闭。C:\Users\maluyao>ssh -N -T -R 0.0.0.0:8867:localhost:443 root@aliyun.maluyao.top 失败!!! C:\Users\maluyao>ssh -N -T -R 8867:127.0.0.1:443 root@aliyun.maluyao.top 成功!!!这里的
localhost在 Windows 上经常会优先解析到 IPv6 的::1(而不是127.0.0.1)。 你的本机 Nginx 虽然能用https://127.0.0.1:443访问,但很可能 没有在::1:443上监听(没开 IPv6 listen)。真正的问题是:Windows 上用
localhost做转发目标时,实际走到 IPv6::1,而本机服务只在 IPv4 上可用
评论
评论加载中……