☰
jump server v2.1.0资源包详解:跳板机部署与SSH审计实践
2026/10/24 17:42:37 网站建设 项目流程

简介:JumpServer是一款开源的堡垒机系统,用于统一管理服务器访问权限并记录操作日志,是运维审计和等保合规的重要工具。v2.1.0适合离线或受控网络环境下的私有化部署,这份RAR压缩包面向运维工程师、系统管理员及安全入门学习者,可解决在线安装易受网络影响、手工配置繁琐等痛点。包内共3个文件,包含一个tar.gz源码包、一个sh一键部署脚本及一个md5校验文件;整体仅6.19MB,携带方便。部署脚本用于自动化初始化和依赖配置,md5文件则确保源码包未被篡改。资源已有556人学习下载,说明该方案获得一定认可。通过这套资料,读者可获得完整源码、校验文件及一键部署脚本,快速搭建JumpServer堡垒机,实现资产管理、操作审计和权限分配;对运维新手也有助于理解部署逻辑与文件组成。

1. jump server 不是一台普通跳板机:它把 SSH 接入变成一条可控流水线

半夜手机响,某公司的运维同学爬起来处理线上故障,想登录那台内网数据库服务器,首先得翻共享文档找口令,口令还分散在几个人手里,谁也说不清谁能登、谁登过。这种场景下,jump server 这类系统就是标准答案:把人、资产、授权收口到一个界面,所有 SSH 连接都经过它代理,操作全程有审计。这份 jump server-v2.1.0 资源包就是一套能直接部署的跳板机方案,包含源码、配置模板和初始化脚本,适合运维、安全工程师、以及想规范服务器访问的团队。下面我按实际部署顺序拆一遍,新手能跟着落地,熟手直接看后面几章的参数和踩坑就够。

2. 拆 core 设计:认证、代理、审计三件事,v2.1.0 是怎么组织代码的

2.1 为什么你需要一台“代理型”跳板机

如果现在只有两三台服务器,直接用 ssh 登录问题不大。但服务器一旦超过十台,或者团队里有人离职,传统直连的毛病就出来了:

  • 口令散落在个人收藏夹、共享文档甚至聊天记录里;
  • 有没有人半夜登过机器、执行过什么命令,完全没记录;
  • 权限只能给到“整台机器”,没法限制“只能跑这个应用的重启脚本”;
  • 目标机的 22 端口被迫对所有人开放,暴露面太大。

jump server 的做法是不再去碰目标机的 22 端口,它在中间加一层代理:用户先登录跳板机,跳板机再拿着资产绑定的系统用户去连目标机。目标机只认跳板机的 IP,其他人从外部扫到 22 端口也无所谓,因为防火墙可以只放行跳板机。

这种“代理型”结构带来的直接好处有三个:第一,口令不用发给每个人,个人拿自己的跳板机账号登录就行;第二,所有会话都能被录下来,出错后可以回放;第三,离职时只要禁用跳板机账号,连目标机的权限也自动收回了。这三点单独拿出来都不算什么,合在一起就是运维规范的基础。

提示:如果你准备在现有网络里加 jump server,最好先梳理好“资产”和“系统用户”两个概念。资产就是你要管理的那台服务器;系统用户是 jump server 用来登录目标机的账号,比如 root 或 deploy。

2.2 认证、授权、审计三个模块怎么配合

这套 v2.1.0 的代码结构里,三个核心模块非常清晰:

  • 认证模块负责“你是谁”。它支持本地账号、SSH Key,也可以对接 LDAP 目录服务。实际部署时,我一般先用本地账号跑通,再考虑对接统一认证。
  • 授权模块负责“你能连哪台”。它维护的是“用户—资产—系统用户”三层映射。也就是说,某个用户被授权到某台资产的某个系统用户,他登录跳板机后才能发起对应连接。
  • 审计模块负责“你干了什么”。它记录登录时间、源 IP、命令列表,并且用会话录制的方式把整段 SSH 交互存成可回放的文件。

这三个模块在资源包里分别落在 apps/users、apps/assets、apps/audits 三个目录。目录结构大致是:

jump_server-v2.1.0/ ├── apps/ │ ├── assets/ # 资产、授权规则、系统用户 │ ├── users/ # 用户、用户组、认证 │ ├── audits/ # 登录日志、命令记录、会话录制 │ └── terminal/ # Web 终端、SSH 代理核心 ├── conf/ │ ├── config.py # 数据库、Redis、监听端口 │ └── settings.py # 业务开关、录制参数 ├── requirements.txt # Python 依赖列表 ├── deploy.sh # 一键初始化脚本 └── README.md

第一次打开资源包,先不要急着跑部署脚本,把 conf/config.py 打开看一遍就行。里面会把数据库连接、Redis 地址、监听端口这些最关键的参数集中放好,改完再用 deploy.sh,会省掉很多来回排查的时间。

2.3 技术栈选型:为什么是 Python 后端 + Web 终端

v2.1.0 后端是 Python,Web 终端是基于 WebSocket 的实时通道,配合 Redis 做会话状态缓存,MySQL 存业务数据。这个组合在一线运维场景里比较常见,原因是 Python 生态里做资产管理、权限校验的现成组件多,部署和二次开发的门槛也低。相比纯 Go 或者纯 Node 的实现,这个组合更适合团队里有人能看懂、能改。

另外,Web 终端和 SSH 代理是两套通道。用户在浏览器里打开终端,实际是 WebSocket 连到 jump server 的 terminal 服务,terminal 服务再通过 SSH 协议连目标机。这个链路里,WebSocket 负责浏览器到跳板机这一段,SSH 负责跳板机到目标机这一段。中间的数据会被审计模块复制一份,用于录制和命令过滤。

2.4 关键配置项:端口、数据库、会话录制参数

部署前先把下面这张表过一遍,大多数配置在 conf/config.py 里都能找到对应项。

配置项默认值建议说明
SSH 代理端口2222生产环境统一改掉用户命令行连跳板机时用的端口
Web 监听端口8080用 Nginx 反向代理后改为内网端口浏览器访问的入口
MySQL 数据库名jumpserver独立库,不要共用字符集必须为 utf8mb4
Redis 数据库序号0单独使用一个 db用于会话缓存,不要和业务缓存混
会话录制目录media/放到 /data 下的大磁盘录制文件增长很快,需要容量冗余
SECRET_KEY随机串首次部署后改掉用于加密密码和会话密钥

参数给到这一步,我一般会先把 MySQL 和 Redis 起起来,然后再回去改 config.py。否则配置文件改完,服务一启动连不上数据库,又要回来排查。

2.5 与纯 SSH Gateway 的差异:日志和命令过滤为什么更重要

纯 SSH Gateway 只做转发,不解析 SSH 协议内容,所以它只能记录“谁在什么时间连了哪台机器”,记录不了具体命令。v2.1.0 这类带 Web 终端和不带 Web 终端的代理,最大的差别在于:Web 终端能拿到明文输入输出,可以在协议层做命令过滤和关键字告警。

比如,你可以配置禁止生产库资产上执行drop database,用户在 Web 终端里敲出来会被直接拦截。纯 SSH Gateway 根本做不到这一点,这就是我坚持选这套方案的原因。当然,Web 终端也有自己的坑,比如浏览器兼容性、粘贴大段命令时的性能问题,这些后面会有排障说明。

2.6 生产部署时组件怎么放:单机验证与多机分离

最小验证环境可以把 Web、终端、MySQL、Redis 全塞在一台机器上,但生产环境我不会这么干。常见做法是拆成三层:数据库和 Redis 一组,jump server 应用一组,再前面挂 Nginx。应用节点可以横向扩展,但终端服务需要和 Web 共用 Redis,才能让用户在一个节点发起连接、另一个节点也能感知会话。

组件分离后,配置文件里要改的是数据库和 Redis 的地址,不能再写127.0.0.1,而要写对应节点的内网 IP。这时候网络策略就很重要,数据库和 Redis 不需要暴露公网,安全组只允许应用节点访问即可。这些在单机部署阶段都是用不到的,但提前知道,后面迁移就不会抓瞎。

3. 部署一套最小可用的 jump server:从解压 rar 到接入第一台 Linux 主机

3.1 环境准备:版本对齐是第一步

v2.1.0 的依赖清单要求 Python 3.6 以上、MySQL 5.7 以上、Redis 3.2 以上。部署前先确认版本,免得跑到一半因为组件太新出现兼容性报错:

python3 --version mysql --version redis-cli info | grep redis_version

如果本机没有 MySQL,可以先用 Docker 起一个,注意指定字符集,否则后面中文资产名很容易报错:

docker run -d \ --name jumpserver-mysql \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=passw0rd \ -e MYSQL_DATABASE=jumpserver \ mysql:5.7 \ --character-set-server=utf8mb4 \ --collation-server=utf8mb4_unicode_ci

这里MYSQL_DATABASE直接创建了库,character-set-server和collation-server两个参数指定了默认字符集。如果不加这两个参数,MySQL 默认的 latin1 会让中文用户名和资产名在入库时变成乱码,后面搜索和导出都会出问题。这是我第一次部署时踩过的坑,当时所有中文资产在列表里都是???,查了半天才发现是建库时没指定字符集。

3.2 解压并安装依赖

rar 包在 Linux 下解压,我习惯用 7z,因为 unrar 在最小化安装里经常没有:

7z x jump_server-v2.1.0.rar -o/opt/jumpserver cd /opt/jumpserver chmod +x deploy.sh

-o后面的目录如果不存在,7z 会创建。解压完成后先给部署脚本加执行权限,否则直接./deploy.sh会报权限不足。

接下来创建虚拟环境并安装依赖:

python3 -m venv venv source venv/bin/activate pip install -r requirements.txt

用虚拟环境不是为了装样子,是避免把依赖装到系统 Python 里,污染其他项目。如果服务器在国内网络,可以临时把 PyPI 源换成内网镜像源,具体地址各家不一样,只要保证能拉通依赖就行。装完之后可以用pip check验证依赖冲突,网络状况差的时候这一步特别有用。

3.3 修改配置:数据库、Redis、密钥

打开conf/config.py,至少要把下面几项改成自己的环境值:

DB_HOST = '127.0.0.1' DB_PORT = 3306 DB_NAME = 'jumpserver' DB_USER = 'jumpserver' DB_PASSWORD = 'your-db-password' REDIS_HOST = '127.0.0.1' REDIS_PORT = 6379 REDIS_DB = 0 SECRET_KEY = 'please-change-me-to-a-random-string'

如果 MySQL 容器已经跑起来了,还要在库里创建专用账号:

CREATE USER 'jumpserver'@'%' IDENTIFIED BY 'your-db-password'; GRANT ALL PRIVILEGES ON jumpserver.* TO 'jumpserver'@'%'; FLUSH PRIVILEGES;

这里注意,SQL 里的'%'表示允许任何 IP 连接。如果 MySQL 和 jump server 在同一台机器,也可以收紧为'localhost'。但如果你把 jump server 单独部署,MySQL 在另一台机器上,一定要给'%',否则连接时会被 MySQL 拒绝。

3.4 初始化数据库并创建管理员

依赖装好、配置改好之后,执行数据库迁移:

python manage.py makemigrations python manage.py migrate python manage.py createsuperuser

makemigrations会根据模型生成迁移文件,migrate把迁移文件应用到数据库。createsuperuser 是交互式的,会依次问用户名、邮箱、密码。邮箱可以直接回车跳过,用户名和密码别用太弱的,因为这是管理后台的入口。

如果后续还要写脚本调用 API,需要再生成一个 API Token,这个可以在 Web 后台的用户详情页里创建,也可以直接通过接口申请,后面进阶章节会用到。

3.5 启动服务并接入第一台主机

本地验证阶段,可以直接用 Django 自带的 runserver 启动:

python manage.py runserver 0.0.0.0:8080

0.0.0.0表示监听所有网卡,这样你才能从自己的电脑访问。生产环境不要这么干,换成 gunicorn 跑,下面只是本地验证:

gunicorn -w 4 -b 0.0.0.0:8080 jumpserver.wsgi:application

服务起来后,浏览器访问http://<server-ip>:8080,用刚才创建的管理员登录。添加资产有两种方式,界面点击最直接,脚本批量导入更快。这里给一个用 API 添加资产的例子:

# 1. 获取 token TOKEN=$(curl -s -X POST http://127.0.0.1:8080/api/token/ \ -d '{"username":"admin","password":"admin123"}' \ | python3 -c 'import sys, json; print(json.load(sys.stdin)["token"])') # 2. 添加一台 SSH 资产 curl -s -X POST http://127.0.0.1:8080/api/assets/assets/ \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name":"web01","address":"192.168.1.10","protocol":"ssh","port":22}'

这段命令先调用登录接口换 token,再用 token 请求资产接口。name是资产显示名,address是目标机 IP,port是目标机 SSH 端口。如果目标机用的不是标准 22 端口,改port就行。响应里会出现id字段,后面给用户授权时要用。

3.6 验证连接:命令行 SSH 直连会被代理拦下来

添加完资产,先别急着在 Web 终端点连接,可以先试命令行通道:

ssh -p 2222 admin@127.0.0.1

这里的admin是 jump server 里的账号,不是目标机的系统用户。jump server 收到连接后,会要求你选择要访问的资产,然后再用资产绑定的系统用户去连目标机。第一次连接时,目标机如果开了 StrictHostKeyChecking,可能会提示指纹确认,这是正常的。整个过程里,目标机看到的连接发起方是 jump server 的 IP,不是你的办公网 IP。这也解释了为什么后面排查问题时,目标机侧的last结果很少能帮上忙。

3.7 给资产绑定系统用户:root 直连还是普通用户

资产添加完成后,还需要给资产绑定一个系统用户,否则 jump server 不知道用它去连目标机时该用哪个账号。常见的做法有两种:直接绑定 root,或者绑定一个有 sudo 权限的应用用户。我一般建议绑定普通用户,少用 root,这样审计记录里还能看到具体是谁通过 sudo 提权执行的命令。

在 Web 界面上,系统用户配置里需要填目标机上的真实账号和密码,或者选择一个 SSH Key。jump server 会把密钥托管起来,连接时自动装载。这里需要注意的是,如果目标机禁用了密码登录、只留密钥,那系统用户必须绑定密钥。密钥权限要设成 600,否则 OpenSSH 会直接拒绝使用。

4. 常见问题与排查:五处最容易翻车的配置点

4.1 现象:Web 页面能打开,但点“连接”后一直转圈

原因:Web 终端服务没有启动,或者浏览器到跳板机的 WebSocket 通道被 Nginx 截断了。很多人只启动了 Django 的 HTTP 服务,忘了 terminal 服务也要跑起来。

解决:确认两个进程都在跑。如果是用 runserver,它其实能同时提供 WebSocket;但如果你接入了 Nginx,就必须把升级协议的请求转发对:

location /ws/ { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 3600s; }

关键就是Upgrade和Connection两个头,少了任何一个,WebSocket 握手都会失败。别问我为什么知道,我第一套环境就是加了 Nginx 后控制台一直报 400。

4.2 现象:命令行连 2222 端口提示 Connection refused

原因:跳板机没有监听 2222 端口,或者防火墙没有放行。

解决:先看监听:

ss -lntp | grep 2222

如果没有任何输出,说明 SSH 代理服务没起来,检查终端服务的日志。如果监听正常,再检查防火墙:

firewall-cmd --add-port=2222/tcp --permanent firewall-cmd --reload

注意,云服务器还要看安全组规则,仅改本机防火墙是没用的。我遇到过在云上把云厂商安全组漏掉的情况,本地ss显示监听没问题,外部就是连不上,翻车翻得很彻底。

4.3 现象:migrate 时报 Duplicate column name

原因:数据库里残留了旧版本的表结构,或者 migrations 目录里有重复的迁移文件。v2.1.0 和新一点的版本混跑时特别容易出现。

解决:先备份数据库,然后检查迁移状态:

python manage.py showmigrations

找到标着[X]的对应迁移,用--fake把它标为已应用:

python manage.py migrate --fake assets 0001_initial

--fake的意思是告诉 Django 这个迁移已经执行过,不再实际跑 SQL,只更新记录。这招能绕过重复列问题,但用不好会掩盖真实的结构差异。我的习惯是先把表结构 diff 出来看一遍,确认只是列重复才用 fake,否则老实手工修库。

4.4 现象:会话录制文件是 0 字节,回放黑屏

原因:录制命令执行依赖 ffmpeg,录制目录权限不对,或者磁盘满了。ffmpeg 如果没装,跳板机不会报错,只是录像文件写不进内容,看起来很像是黑匣子。

解决:装上 ffmpeg,然后确认 media 目录存在且可写:

yum install -y ffmpeg mkdir -p /data/jumpserver/media chown -R jumpserver:jumpserver /data/jumpserver/media

录制文件从产生到可回放,中间其实经过了一个临时写入和转码的过程,所以刚结束的会话几秒内看不到录像很正常。如果过了几分钟还是 0 字节,再去查 ffmpeg 的日志。

4.5 现象:管理员添加了资产,普通用户登录后看不到

原因:授权规则没覆盖该用户,或者用户和资产不在同一个规则节点下。v2.1.0 的授权不是简单的“勾选即生效”,它会按节点匹配继承。

解决:在授权规则里创建一条“用户组→资产组→系统用户”的映射。检查时注意,用户登录后默认只能看到规则命中的资产,不是所有资产。如果你建的规则只授权了/default/节点下的资产,而新资产放在/AWS/节点,用户看不到是正常的:

# 伪代码:授权规则的关键匹配逻辑 if user in rule.users and asset in rule.assets and system_user in rule.system_users: return True

提示:改完授权规则后,用户不需要重启服务,重新登录或者刷新资产列表即可。如果还是看不到,查看用户所属用户组,规则是否绑定的是用户组而非单个用户。

5. 进阶技巧:批量导入资产与连接自测脚本

5.1 用 API 批量导入资产

如果手上有一百台机器,Web 界面点起来太慢。我一般从 CMDB 导出一份 CSV,然后用脚本批量调 API。先看 CSV 格式:

name,address,protocol,port,node web01,192.168.1.10,ssh,22,/default/ web02,192.168.1.11,ssh,22,/default/

然后跑这个 Python 脚本:

import csv import os import requests API_BASE = "http://127.0.0.1:8080/api" TOKEN = os.getenv("JS_TOKEN") headers = {"Authorization": f"Bearer {TOKEN}"} with open("assets.csv") as f: for row in csv.DictReader(f): r = requests.post(f"{API_BASE}/assets/assets/", headers=headers, json=row) if r.status_code != 201: print(f"failed: {row['name']} -> {r.text}")

脚本核心是遍历 CSV 的每一行,POST 到资产接口。注意 token 不要写在代码里,用环境变量JS_TOKEN传入,避免文件被上传到 git 仓库泄密。

5.2 连接自测脚本

部署完成后,我最少会跑一遍这样的自测,确保 2222 端口通、代理能转发:

for ip in web01 web02; do nc -zv "$ip" 2222 && echo "$ip ok" || echo "$ip fail" done

但nc只能测端口通不通,测不了认证链路。所以我还会在脚本里额外调一次 WebSocket 的握手接口,确认终端服务在线。自从有一次因为忘记启动终端服务,导致整个环境“看起来正常、实际连不上”之后,我每次部署完都强制走一遍连接自测,把这个脚本放到部署文档的最后一步,已经成了固定习惯。

希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询