ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

secureCRT-7.0.0实战:SSH2公钥、端口转发与日志脚本配置

secureCRT-7.0.0实战:SSH2公钥、端口转发与日志脚本配置

简介:SecureCRT 7.0.0 是面向 IT 运维、网络管理员及开发测试人员的 64 位终端仿真与文件传输工具包,主要用于 shell 远程登录、服务器维护及多协议连接管理。压缩包共93个文件,约15.86MB,含26个dll运行库、14个vbs与6个py脚本、5个exe主程序,以及key、mnu、fon、chm等配置、菜单、字体和帮助文档,另有SecureFX组件,可配合完成SSH、Telnet、RLogin、Serial、FTP/SFTP等连接与传输。该版本提供标签式界面、会话管理、脚本自动化、宏录制回放和多语言支持,能保存常用会话配置,并借助VBScript、JScript、Python扩展批量操作。对于频繁登录路由器、交换机、Linux/Unix主机的场景,可通过会话切换和脚本减少重复操作,mnu、fon等文件也便于菜单与字体适配,降低重复配置成本并提升远程排障效率,也可用于搭建安全终端环境。目前已有284人学习下载,适合需要集中管理远程会话、调试网络设备的运维人员参考。

1. 从一堆乱窗口说起:secureCRT-7.0.0 到底治什么病

凌晨两点排查一台业务机的 shell 环境变量,屏幕上开着七个终端窗口,最后一个窗口的报错往上翻三百行时才发现滚屏缓冲早被冲掉了,只能重跑一遍命令把现场再造出来。secureCRT-7.0.0 就是冲着这类场面来的:它是一款终端仿真客户端,把 SSH2 会话、认证方式、日志留痕、脚本触发这四件事收进同一个界面,本质仍然只是给你一个干净的 shell,但把这个 shell 周围最容易丢的东西都钉死了。适合每天在内网多台机器之间跳、需要回看历史输出、需要把重复命令固化成脚本的运维和开发;只是想临时连一次服务器的人,用它反而显重——装完还要配会话、配编码、配日志路径,前期投入不小。判断标准很简单:一周之内你会连同一批机器超过三次,那这套配置就值回票价。

2. 会话与认证落地:把密码登录换成 SSH2 公钥

2.1 建会话之前先改全局默认项

很多人装完直接新建会话填 IP 就开干,跑两天发现中文全是方块、翻页翻不上去、粘贴个多行命令全乱套,然后又回头一个个会话去改。正确顺序是先改全局默认,再建会话,新会话自动继承。

常见做法是打开「全局选项 → 常规」把配置文件夹指到一个非系统盘的固定路径,比如D:\crt-config。系统盘重装或者换了机器,这个目录整个拷走就能还原工作环境,这是后面第 6 章做团队分发的前提。接着在「全局选项 → 默认会话」里改这几项:

选项位置建议值为什么
终端 → 仿真Xterm多数 Linux 发行版的 terminfo 认这个,方向键和功能键不会错位
终端 → 外观 → 字符编码UTF-8和服务端 locale 对不上时才会乱码,先统一到 UTF-8 再谈排查
终端 → 仿真 → 回滚缓冲20000 行默认几百行,编译日志一刷就没了
终端 → 反空闲每 60 秒发送一个字符网络设备和服务端都可能有空闲超时,这一步能挡掉一半的「莫名断开」

改完默认会话,新建的每个会话都带这些值。这里有个容易忽略的点:字符编码是会话级参数,不是全局参数。你在默认会话里改了,只影响之后新建的会话,已经存在的会话要单独进去改一遍。我一般会在改完之后随便连一台机器跑一句locale验证:

# 确认服务端 locale 和终端编码是否一致 locale echo $LANG # 输出里出现 zh_CN.GBK / zh_CN.GB18030,说明服务端不是 UTF-8 # 两条路:要么把会话编码改成对应值,要么把服务端改成 UTF-8,别两边各改一半

locale输出的LC_CTYPE决定字符集,LANG是兜底值。如果LC_ALL有值,它会覆盖前面两个,排查时先看它。改服务端是根治办法,改客户端是快办法,但一个团队里客户端设置五花八门的时候,统一服务端反而省事。

2.2 公钥登录:一次配对,后面不再输密码

密码登录在跳板机上被审计、被强制改期、被复杂度策略卡住,是常态。换成 SSH2 公钥认证之后,登录动作就只剩一次密钥交换。生成密钥对这件事在哪做都行,我习惯在跳板机上做,然后把私钥拉回本地:

# -t 密钥类型;-b 位数;-C 注释用来区分环境;-f 指定文件名避免覆盖默认 id_rsa ssh-keygen -t rsa -b 4096 -C "ops-bastion" -f ~/.ssh/id_rsa_ops # 一路回车会生成两个文件: # id_rsa_ops 私钥,留在客户端,权限必须是 600 # id_rsa_ops.pub 公钥,可以随便传 # 把公钥推到目标机的授权列表 ssh-copy-id -i ~/.ssh/id_rsa_ops.pub ops@10.0.0.21

-b 4096不是越大越好。老一点的网络设备、老版本的 SSH 服务端对 4096 位的 RSA 支持没问题,但对某些新式密钥类型(比如 ed25519)反而认不出来。内网里混着一批老设备的时候,老老实实用 RSA 2048 兼容性最好,4096 只在你确认全链路都吃得下的时候再用。

手工追加公钥的时候,权限位是最高频的翻车点:

# 在目标机上执行,三个权限位错一个,公钥认证就会静默退回密码认证 chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chmod 700 ~ # 家目录本身也不能是 777 # 开了 SELinux 的机器还要修上下文,否则 sshd 读不到文件 restorecon -R -v ~/.ssh

chmod 700 ~这条最容易被忽略。有人为了图方便把家目录设成 755,sshd 在严格模式下会直接拒绝公钥认证,日志里只留一句含糊的失败原因,看起来像密钥不对,其实是目录权限太宽。

接下来是客户端侧。在会话选项 → 连接 → SSH2 → 认证里,把认证方式调成 PublicKey 并指到私钥文件。这里有一个 7.0 特有的坑:新版 OpenSSH 生成的私钥默认是BEGIN OPENSSH PRIVATE KEY格式,7.0 这个年纪的客户端只认老式的 PEM 头(BEGIN RSA PRIVATE KEY)。直接选文件会提示格式不支持,转一下就行:

# 只转换格式,不动密钥内容,会就地覆盖,先备份 cp ~/.ssh/id_rsa_ops ~/.ssh/id_rsa_ops.bak ssh-keygen -p -m PEM -f ~/.ssh/id_rsa_ops # -m PEM 指定输出格式;-p 表示改密码短语(直接回车两次即为空)

转换完再在客户端里选一次文件就能用了。私钥带了密码短语的话,7.0 支持在会话里缓存,但缓存是内存级的,客户端一关就没了,别指望它跨会话生效。

2.3 会话文件的目录结构与批量生成

secureCRT-7.0.0 的会话不是数据库,就是一个目录树加一堆文本文件,Sessions 目录下面的文件夹结构和你界面上看到的文件夹一模一样,每个会话对应一个.ini。这意味着会话是可以批量造的——把一份调好的会话复制成几十份,只改主机名。

#!/usr/bin/env bash # 用一份模板批量生成会话文件,只替换主机名 set -euo pipefail TPL="$HOME/crt-config/Sessions/生产/模板.ini" OUT="$HOME/crt-config/Sessions/生产" # hosts.txt 每行两列:会话名 主机地址 while read -r name host; do sed -e "s|^S:\"Hostname\"=.*|S:\"Hostname\"=$host|" \ "$TPL" > "$OUT/$name.ini" done < hosts.txt

这段脚本的核心是sed的替换表达式。^S:\"Hostname\"=是锚定到行首的键名匹配,只替换这一行,其它配置(编码、日志路径、端口转发规则)原样继承模板。键名不要照抄我这里的写法,先手工建一个会话,改一下主机名保存,用文本对比工具看这两个文件的差异,差异行就是你要替换的那一行,把它抄进脚本里。不同版本的 ini 键名会有出入,以你本地实际导出为准。

while read -r里的-r是防止反斜杠被解释,hosts.txt用空格或制表符分隔都行。生成完重启客户端,会话树里就多出一批,点开即用。这套办法适合一个项目几十台机器、命名规则统一的场景,比一个个手点快得多,也不容易漏配某一项。

3. 端口转发与多跳:三台机器之间只留一条可控链路

3.1 本地转发:把只监听回环的服务拉到本机

内网里最常见的场景:某台数据库只监听127.0.0.1:3306,你在办公网,中间隔着一台跳板机。直接在跳板机上开客户端连数据库不行,因为跳板机上没有图形化工具;把数据库端口对外放开更不行。本地转发解决的正是这个。

先在命令行里把逻辑跑通,再搬到客户端里配,这样出问题好定位:

# 在能连到数据库的那台跳板机上执行 # 本机 13306 -> 跳板机视角的 10.0.2.15:3306 ssh -N -L 127.0.0.1:13306:10.0.2.15:3306 ops@10.0.0.21 # -N 表示只做转发,不在远端执行 shell # -L 是本地转发 # 显式写 127.0.0.1 而不是留空,避免监听在所有网卡上 # 排错阶段别加 -f 后台运行,日志看不到就抓瞎

参数里最容易搞混的是第三个字段。10.0.2.15这个地址是从跳板机出发能解析、能路由到的地址,不是你自己这台机器视角的地址。你本地机器根本不认识10.0.2.15,它只认识127.0.0.1:13306。这个视角差异是新手第一个卡点,配错了表现为「连接被拒绝」或者「连接超时」,两种报错对应的是完全不同的原因。

搬到客户端里,位置在会话选项 → 连接 → Port Forwarding → 添加,类型选 Local:

字段填什么含义
Local Port13306你本机上要占用的端口,冲突就换一个
Remote Host10.0.2.15跳板机视角的目标地址,域名也行
Remote Port3306目标服务端口

配好之后连着这个会话,本地工具连127.0.0.1:13306就等于连到了数据库。注意转发规则是跟着会话走的,会话断开转发就没了,所以这个会话最好设成自动重连。

本地转发还有一层用法是做端口对照。同一个目标服务,你可以开多条规则映射到不同本地端口,比如 13306 和 13307 分别指向主库和备库,工具里切端口比切会话快。

3.2 远程转发:让内网机器主动回连

反过来的一种情况:你在办公网,需要访问一台藏在很深处、只能出不能进的内网机器上的 Web 服务。这台机器能连到跳板机,但跳板机连不回去。这时候方向要反过来,由内网机器发起连接,把远端端口映射回来。

# 在内网机器上执行:把本机 8080 映射到跳板机的 18080 ssh -N -R 127.0.0.1:18080:127.0.0.1:8080 ops@10.0.0.21 # -R 是远程转发,前一个 127.0.0.1 是跳板机上的绑定地址

关键在跳板机上的绑定地址。默认情况下 sshd 的GatewayPorts是no,远端转发只会绑定在跳板机的回环地址上,也就是说只有登录到跳板机本机的人才能访问这个 18080。这个默认值是故意的,改成yes会让转发端口绑定到所有网卡,等于把一个内网服务摊开给整个网段。

我见过不止一次有人为了图省事把GatewayPorts yes写进 sshd 配置,然后忘了删。判断要不要开的标准:如果只有你自己登录到跳板机本机去访问,保持默认;如果确实需要同网段的同事访问,先确认这台服务的鉴权做得够不够,再考虑开,并且配合防火墙限源。

远程转发还有个隐性限制:连接断了规则就没了,而内网机器往往不会主动重连。想让它长期挂着,得在客户端里给这个会话配自动重连,或者干脆用系统服务托管一条ssh -N -R命令。

3.3 多跳串联与心跳保活

三层网络的时候,别在跳板机上再装一个客户端。用一条命令串起来:

# -J 接受一个逗号分隔的跳板列表,从外到内依次连接 ssh -J ops@10.0.0.21 ops@10.0.3.8 # 等价于先连 10.0.0.21,再从这台机器上发起第二跳 # 老版本 OpenSSH 没有 -J,需要在 ~/.ssh/config 里用 ProxyCommand 写

-J的好处是第一跳的认证在本地完成,两跳之间不用手工输两次密码,密钥也是本地这把。缺点是中间任何一跳断了整条链就断,没有断点续连。

心跳保活分两头配:

# 客户端侧,写进 ~/.ssh/config 的 Host * 段 ServerAliveInterval 30 ServerAliveCountMax 3 # 含义:每 30 秒发一个探测包,连续 3 次没响应才判定断开 # 也就是最多容忍 90 秒的网络抖动 # 服务端侧对应的是 /etc/ssh/sshd_config 里的 # ClientAliveInterval 和 ClientAliveCountMax,语义一样

客户端侧的这两项在 secureCRT-7.0.0 里对应「会话选项 → 终端 → 反空闲」,可以选发送协议规定的空字符,也可以发一个固定字符串。发字符串的做法在 shell 里会留下回显,看着烦,我一般直接发空字符。

反空闲解决的是 NAT 表和防火墙会话老化的问题,解决不了服务端主动踢人。如果服务端配了ClientAliveCountMax 0或者登录 shell 里有TMOUT,客户端发什么都没用,得从服务端侧查。这个区别在排查时很关键:断开的时间点是不是固定的?固定间隔断开通常是服务端或中间设备的老化策略,随机断开才是网络问题。

4. 日志与脚本:让重复命令自己跑完并留下痕迹

4.1 自动日志:按会话分目录、按天切分

排障最痛的从来不是当时看不懂输出,而是事后想再看一眼却没有。日志功能要开在会话级别,不要指望全局开关能覆盖所有场景。

配置项建议值说明
日志文件名D:\crt-logs\%S\%Y-%M-%D.log%S是会话名,日期宏按软件提示填
记录模式追加覆盖模式下同一天重连会丢前面那段
时间戳每行前加事后对齐多台机器的日志时全靠它
连接时自动开始勾选不勾就得每次手动点,一定会忘

宏的具体写法以「会话选项 → 终端 → 日志文件」旁边的提示为准,不同版本支持的宏不完全一样。%S展开成会话名这件事很关键——它让日志天然按机器分目录,几十台机器的日志不会糊在一个文件里。

落地时有三个现实问题。第一是磁盘,一台机器一天的交互式日志几百 KB 到几 MB,几十台机器跑一年就是几十 G,路径千万别指到系统盘。第二是网络盘,日志写到映射盘上,网络一抖客户端就卡住甚至崩掉,本地盘最稳。第三是脱敏,日志会把你敲过的所有东西原样记下来,包括mysql -p后面跟着的明文密码、export出来的密钥变量名。打开日志之前先想清楚这个目录谁能看。

日志的另一个用法是做变更留痕。改配置之前把当前输出打一份,改完再打一份,两份日志文件按时间排序就是完整的变更记录,比事后回忆靠谱得多。

4.2 脚本引擎:VBScript 和 Python 怎么选

7.0 这个版本提供两套脚本入口:VBScript 是内建的,开箱即用;Python 需要在「全局选项 → 脚本」里指到一个本机解释器,指不对就报找不到模块。选哪套不用纠结——你手边有什么环境用什么。VBScript 的优势是零依赖,任何一台装了这个客户端的 Windows 机器都能直接跑;Python 的优势是你可能已经有一堆现成的库。

我一般这么分:只在这一个客户端里跑、逻辑不超过五十行的小动作,用 VBScript;需要读 CSV、算哈希、发 HTTP 请求的,用 Python,那些活儿在内建脚本里做太憋屈。

脚本的触发方式有两种。一是手工执行,脚本菜单里选文件;二是绑定到会话的登录动作上——「会话选项 → 连接 → 登录动作」里可以指定一个脚本,会话一连上就自动跑。第二种是批量采集的关键,配上第 2 章那种模板会话,一次打开二十个标签页,每个都自动跑一遍采集,人只需要等。

4.3 一个能跑的例子:批量采集版本信息

下面这段是 Python 脚本,作用是往当前标签页发一条命令,等提示符回来,把中间的输出存文件。这类脚本看着简单,坑几乎全在时序上。

# -*- coding: utf-8 -*- # 对当前活动标签页发命令,抓输出落到本地文件 def main(): tab = crt.GetScriptTab() screen = tab.Screen # 关掉异步刷新,否则 WaitForString 会在半行输出上误匹配 screen.Synchronous = True # 关分页,不然输出会停在 --More-- 等按键 screen.Send("terminal length 0\r") screen.WaitForString("#", 5) # 第二个参数是超时秒数 screen.Send("show version\r") out = screen.ReadString("#", 10) # 读到下一个提示符为止 with open(r"D:\crt-logs\version.txt", "a", encoding="utf-8") as f: f.write(out) main()

逐项说清楚。crt.GetScriptTab()拿到当前激活的标签,脚本是挂在标签上跑的,不是全局的,所以要在目标会话里执行。Synchronous = True这一行是整段脚本的命门,不设的话屏幕缓冲区在后台异步填充,WaitForString可能在只收到半行的时候就匹配成功,取回来的输出是残缺的——这种 bug 表现为「大部分时候正常,偶尔少几行」,最难查。Send里的\r是回车,不是\n,终端类命令一律用\r。WaitForString和ReadString的第二个参数是超时秒数,省略就是无限等,脚本会卡死在那儿,必须显式给。

提示符"#"要按实际改。网络设备常见#和>,普通用户是$,有些发行版还会在提示符里塞颜色控制字符,导致字符串匹配不上。稳妥做法是先用一个不匹配任何东西的字符串跑一次,把ReadString的结果打印出来,看看真实的提示符长什么样,再拿去当匹配串。

5. 排查清单:五类高频翻车现场与定位顺序

5.1 中文变方块或者显示成问号

现象:ls出来的中文文件名全是问号,cat一个 UTF-8 文件满屏乱码,但同一台机器换个客户端就正常。

原因:客户端编码和服务端 locale 不是一套。7.0 的会话编码是会话级参数,改建会话时如果是从一个老会话复制来的,编码会跟着老会话一起继承。

解决:先在服务端跑locale看LC_CTYPE,再用「会话选项 → 终端 → 外观 → 字符编码」对齐。服务端是zh_CN.GBK就选 GBK,是en_US.UTF-8或zh_CN.UTF-8就选 UTF-8。两边都改一半是最糟的状态,改完记得把终端窗口重开一个,编码切换不会作用于已有回滚缓冲里的内容。

5.2 配了公钥还是让输密码

现象:私钥选了,用户名对了,登录还是弹密码框,输对了也能进,就是公钥没生效。服务端日志里只有一句「Authentication refused」。

原因:按出现频率排,一是权限位,家目录或.ssh或authorized_keys权限太宽;二是 SELinux 上下文不对;三是客户端加载的私钥格式不被 7.0 识别,静默跳过;四是 sshd 配置里PubkeyAuthentication被关掉了。

解决:先在服务端看/var/log/secure(或对应日志),公钥认证失败会写明原因。权限问题按第 2 章的chmod 700/600一遍过;SELinux 用restorecon -R -v ~/.ssh;格式问题用ssh-keygen -p -m PEM -f转一次。排查顺序建议从服务端日志开始,别一上来就怀疑密钥本身,密钥本身出错反而是概率最低的。

5.3 连接建立阶段直接失败,提示没有共同的算法

现象:连一台新装的服务器,TCP 能通,但握手阶段就断,客户端提示找不到匹配的密钥交换算法或加密算法。

原因:7.0 这个年纪的客户端只支持到当年的算法集合,而新版本 OpenSSH 默认关掉了ssh-rsa(SHA-1 签名)和一批老式密钥交换。两边各退一步才能谈拢。

解决:优先在客户端侧放开——「会话选项 → 连接 → SSH2」里的密钥交换、加密、MAC 三个列表,把服务端支持的算法勾上并拖到前面。服务端侧改配置(PubkeyAcceptedAlgorithms、HostkeyAlgorithms之类)是下策,会把整台机器的安全基线拉低,只在前者确实做不到的时候用,而且改完记一笔,别让它烂在配置文件里。

5.4 挂机一段时间后会话无响应,按键也没反应

现象:放那儿吃个饭回来,窗口还在,敲什么都没回显,也不报断开,点关闭才提示连接已丢失。

原因:中间设备的会话表老化、服务端的空闲超时、或者客户端反空闲没开。判断依据是断开的时间间隔——每次都是整 5 分钟、整 30 分钟,那是策略;时间随机,那是网络。

解决:客户端开反空闲(第 3.3 节),间隔设得比最短的那个超时值小一半。同时去服务端确认ClientAliveInterval和登录 shell 里的TMOUT。如果两头都配了还断,就要看中间有没有负载均衡或者防火墙做了透明老化,这种情况要么缩短心跳间隔,要么干脆用脚本定时发一条无害命令。

5.5 粘贴多行命令时前面几行被提前执行

现象:从文档里复制一段十行的部署脚本粘进终端,中间某行报错,后面几行还是照跑,跑到一半系统处于半完成状态。

原因:终端把粘贴进来的每个换行都当成回车,一行行往下推,没有任何中间暂停。7.0 这个版本没有 bracketed paste 那种把整段粘贴当成一次输入的机制。

解决:三个办法按场景选。少量命令用「粘贴前确认」,好歹能在执行前看一眼;成段的脚本先在本地编辑器里过一遍,确认没有交互式命令(rm -i、read、passwd这类),再粘;真正要批量跑的,写成脚本文件用scp传上去执行,或者用第 4 章那种逐行Send+WaitForString的方式控制节奏。最后一种最慢但最不会出岔子。

6. 配置备份与分发:把一个人的顺手变成一群人的基线

配置能不能带走,决定了这套东西是一次性投入还是长期资产。secureCRT-7.0.0 的所有个性化设置都在两个目录里:Sessions放会话,Config放全局选项、配色、脚本路径、日志模板。把这两个目录一起打包,拷到另一台机器上指过去,工作环境就完整还原了。这件事的核心不在备份,在于把它做成可复现的基线。

我的做法是维护一个「基线会话」:把编码、回滚缓冲、反空闲、日志模板、密钥路径全部调好,其余所有会话都从它复制。复制完之后只允许改三样东西——主机名、端口、会话名。这条约束听起来死板,但它保证了任何一台机器的会话都是同一套行为,出问题时可以排除掉配置差异这个变量。

版本管理也可以接进来。会话文件是纯文本,能 diff 能合并,扔进内部仓库是可行的,但有两条红线:一是仓库必须是私有的,Sessions目录里明晃晃写着全部内网地址和主机名;二是私钥绝对不能跟着进去,把密钥路径写进会话配置没问题,把私钥文件本身放进去就是事故。我一般会在仓库根目录放一个.gitignore,把*.pub之外的所有密钥文件排除掉,再加一条对Config/下缓存文件的忽略规则。

验证基线有没有真的生效,我用一个很笨但有效的办法:在干净机器上还原配置,打开三个不同类型的会话(一台 Linux、一台网络设备、一台带端口转发的),分别做三件事——locale看编码、翻回滚缓冲看行数、连转发端口看通不通。三件事都过,基线就是可用的。这个检查清单我写在仓库的 README 里,谁改配置谁跑一遍。

表格式的检查清单比文字描述好执行:

检查项操作通过标准
编码连 Linux 机跑locale再看中文文件名中文正常显示
回滚跑dmesg后往上翻能翻到 5000 行以前
公钥断开重连三次全程不弹密码框
日志连一次后去日志目录看有当天的文件且带时间戳
转发本地连127.0.0.1:13306能握手,不是连接被拒

最后说个我自己的教训。早几年我把配置随手放在默认路径,系统重装前觉得「回头再导」,结果重装完发现默认路径在用户目录下,跟着一起没了。重建那三十几个会话花了大半天,而且有两条端口转发规则根本没想起来,直到一周后有人反馈连不上某个内部页面才补回来。从那以后我每次装完客户端,第一件事就是把配置目录挪到独立盘符,第二件事是把Sessions和Config一起打包传一份到内部存储,第三件事是在新会话建好之后立刻对着上面那张表走一遍。这三步加起来不到五分钟,能挡掉后面所有的重建成本。希望帮到你。

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

返回列表