模拟实现堡垒机

一、前言

很多人学习堡垒机,只知道堡垒机是跳板机,但是最核心的"二传手"模型理解不到位。

堡垒机本质不是让你登录到堡垒机shell,再手动ssh连后端服务器(传统跳板模式);现代堡垒机核心是协议代理(二传手):用户的命令发给堡垒机,堡垒机把命令转发给后端目标资产;目标资产输出返回堡垒机,堡垒机再回传给用户。堡垒机充当中间的"二传手",用户和后端服务器之间永远没有直接TCP连接,流量全部经过堡垒机中转、解析、审计。

二传手比喻:

用户把球(指令)传给堡垒机(二传手),堡垒机收到球,校验、记录,再传给目标服务器;服务器回球(输出),再经由堡垒机传回用户。整个过程,用户和目标服务器不直接传球。堡垒机在中间接收、转发、监控,这就是堡垒机的代理二传模型。

传统跳板机:两次独立SSH连接,用户登录跳板机操作系统,再在跳板机上执行ssh连接内网机器。跳板机只是一台中间主机,没有解析协议流量,无法细粒度审计命令。

堡垒机二传手代理模式:应用层代理,解析SSH协议流,流量双向转发;可以实时捕获键盘输入、拦截高危命令、全程录屏审计,这是二者最本质区别。

二、堡垒机二传手架构原理

2.1 网络拓扑

plaintext

运维客户端 ↔【堡垒机(二传手代理层)】 ↔ 内网目标服务器

  • 内网服务器不对外开放公网端口,仅允许堡垒机IP访问22端口
  • 运维客户端只能访问堡垒机,无法直连内网资产
  • 堡垒机作为二传手,维护两条独立连接:
  1. 连接A:客户端 ↔ 堡垒机
  2. 连接B:堡垒机 ↔ 目标内网服务器

两个连接互相独立,堡垒机负责把连接A的数据拷贝转发到连接B;连接B的输出拷贝转发回连接A,同时在转发过程中抓包、审计、高危命令拦截。

2.2 二传手完整工作流程

  1. 身份认证:客户端连接堡垒机,堡垒机校验账号、MFA,确认用户身份。
  2. 权限校验:查询该用户是否有权访问目标服务器,允许的操作范围。无权限直接拒绝连接。
  3. 建立后端连接(二传手准备):堡垒机主动发起SSH连接到内网目标服务器(使用托管的资产账号密码,用户无需知道后端服务器密码)。
  4. 双向流量转发(核心二传阶段)
  • 用户输入指令 → 发给堡垒机
  • 堡垒机(二传手)读取数据,记录命令日志,匹配高危命令规则(如rm -rf、drop table),命中则阻断
  • 校验通过后,堡垒机将指令转发给内网服务器
  • 内网服务器执行完成,输出结果返回堡垒机
  • 堡垒机记录输出日志,再把结果转发回运维客户端
  1. 会话结束:任意一方断开连接,堡垒机关闭两条连接,保存完整会话录像与审计日志,用于事后追溯。

2.3 二传手代理 vs 老式跳板机(面试重点)

模式 工作方式 能不能解析命令 审计能力

老式跳板机 两次独立SSH,用户登录跳板操作系统 不能,流量透传,跳板只是TCP转发 只能记录登录跳板的日志,无法审计后端命令

堡垒机二传手代理 堡垒机作为协议代理,中间转发双向流量 可以解析SSH应用层协议 实时命令审计、高危阻断、会话录屏、文件传输审计

关键点:跳板机是"通道";堡垒机二传手是会看懂数据包内容的中间人,不是单纯的TCP管道。

三、简易模拟实现(Go语言,最小二传手模型)

说明:代码仅演示二传手双向转发核心逻辑,不含完善认证、权限、命令审计;生产级堡垒机(JumpServer)在此基础上增加4A能力。

依赖: golang.org/x/crypto/ssh

go

package main

import (

"io"

"log"

"golang.org/x/crypto/ssh"

"net"

)

// 二传手转发函数:双向拷贝数据

func proxyPipe(in io.ReadWriter, out io.ReadWriter, name string) {

go func() {

buf := make(\[\]byte, 1024)

for {

n, err := in.Read(buf)

if err != nil {

log.Printf("%s read closed: %v", name, err)

return

}

log.Printf("%s 捕获流量:%s", name, string(buf:n))

_, err = out.Write(buf:n)

if err != nil {

log.Printf("%s write error: %v", name, err)

return

}

}

}()

}

func handleClient(conn net.Conn) {

defer conn.Close()

log.Println("新客户端接入")

复制代码
// ========== 二传手:堡垒机主动连接后端目标服务器 ==========
targetAddr := "192.168.1.100:22" //内网目标服务器
config := &ssh.ClientConfig{
	User: "root",
	Auth: []ssh.AuthMethod{
		ssh.Password("123456"), //资产托管密码,用户不知道
	},
	HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
targetClient, err := ssh.Dial("tcp", targetAddr, config)
if err != nil {
	log.Println("连接后端资产失败:", err)
	return
}
defer targetClient.Close()

session, err := targetClient.NewSession()
if err != nil {
	log.Println("创建session失败:", err)
	return
}
defer session.Close()

// 开启终端
modes := ssh.TerminalModes{
	ssh.ECHO:          1,
	ssh.TTY_OP_ISPEED: 14400,
	ssh.TTY_OP_OSPEED: 14400,
}
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
	log.Println("请求pty失败", err)
	return
}
stdin, _ := session.StdinPipe()
stdout, _ := session.StdoutPipe()
stderr, _ := session.StderrPipe()
if err := session.Shell(); err != nil {
	log.Println("start shell err", err)
	return
}

//===== 二传手双向转发核心:客户端 <-> 后端服务器 =====
proxyPipe(conn, stdin, "客户端→后端")
proxyPipe(stdout, conn, "后端→客户端")
proxyPipe(stderr, conn, "后端错误输出")

// 阻塞等待会话结束
_ = session.Wait()
log.Println("会话结束")

}

func main() {

listener, err := net.Listen("tcp", "0.0.0.0:2222")

if err != nil {

log.Fatal("监听失败", err)

}

log.Println("堡垒机二传手代理启动,监听 :2222")

for {

conn, err := listener.Accept()

if err != nil {

continue

}

go handleClient(conn)

}

}

代码解读(二传手核心)

  1. proxyPipe 就是二传手转发函数:一边读、一边写,双向搬运流量;并且打印捕获到的数据,模拟审计。
  2. 客户端连接堡垒机2222端口;堡垒机内部主动去连接内网目标服务器。
  3. 两条独立IO流,堡垒机在中间转发,客户端永远拿不到后端服务器账号密码。
  4. 在 proxyPipe 函数里,我们可以增加规则匹配:检测 rm -rf / 、 truncate 等高危命令,直接阻断写入,实现事中控制。

缺陷:demo仅演示二传转发逻辑,缺少:RBAC权限、MFA认证、会话录像、命令黑白名单、密码自动轮换、日志持久化。生产堡垒机JumpServer、Teleport就是在这个二传代理模型之上完善4A体系。

四、堡垒机二传手模型的安全价值

  1. 资产凭据托管:运维人员不需要知道内网服务器账号密码,堡垒机二传手代持密码,密码自动轮换,减少泄露风险。
  2. 切断直连链路:内网服务器不暴露公网,所有访问入口收敛到堡垒机单点。
  3. 事中实时控制:二传手在转发命令时解析内容,可以实时拦截高危操作,不是只能事后看日志。
  4. 完整审计追溯:所有输入输出全部经过二传手,可以完整记录、录屏,满足等保2.0运维审计要求。

五、常见误区

误区1:堡垒机=跳板机

跳板机只是两次ssh跳转,没有二传手代理。现代堡垒机核心就是协议代理二传手模型,流量经过堡垒机解析,不是单纯TCP透传。

误区2:堡垒机是中转TCP管道

普通TCP端口转发只是把字节流原样搬运,看不懂内容。堡垒机二传手是应用层协议代理,能读懂SSH协议里的命令字符,这是本质区别。

六、总结

堡垒机最核心思想就是二传手代理模型:堡垒机作为中间人,维护两条独立连接,双向转发客户端与目标资产之间的SSH流量,同时解析流量、权限校验、审计、阻断高危操作。

这个模型,也是JumpServer开源堡垒机底层核心原理。

本文的极简Go代码,剥离了复杂4A模块,只保留二传手转发逻辑,方便理解底层原理。

后续可以扩展:增加命令黑名单阻断、会话录像存储、RDP协议代理、数据库MySQL协议代理。

博主:网络安全开发

标签:#堡垒机 #JumpServer #二传手 #协议代理 #Go实战 #运维

相关推荐
Highcharts.js1 小时前
Highcharts 发布16项最新安全公告
人工智能·安全·性能优化·highcharts·可视化图表
救救孩子把2 小时前
AI面试八股文-14_14-MCP-Skill-Function Calling
人工智能·安全·面试·职场和发展·推理·mcp·functioncall
听说6665 小时前
信息安全工程师 - 第二十二章 网站安全需求分析与安全保护工程
网络·安全·web安全·网络安全·系统安全
大翻哥哥5 小时前
安全密码库:一款 Windows 本地离线密码管理器,数据只保存在自己的电脑上
安全
buddyMe智能助手6 小时前
长任务拆给谁?把专门化智能体存成可复用、会增长的「选项」
人工智能·深度学习·安全·机器学习·aigc
leizhen198408096 小时前
Vibe Coding:门槛降了,但判断力成了新的门槛
人工智能·安全·ios
遇印记9 小时前
应用层,网络管理
运维·网络·windows·学习·安全
无障碍研究院9 小时前
2026TADC|李璀:从标准走向落地,拆解无障碍产品合规实操方案
安全·web安全
qq_443132419 小时前
数字资产安全治理平台是什么:定义、核心能力与选型要点
网络·安全