1. 为什么在Kali里折腾SSH和防火墙值得单独写一篇
很多人第一次在Kali上开SSH,都是被逼的。要么是虚拟机里敲命令太憋屈,想用宿主机终端连进去;要么是手头只有一台笔记本,想把Kali当远程跳板机跑扫描任务;要么是实验室里几台机器要互传文件,懒得插U盘。结果一上手就发现,Kali的SSH默认状态跟Ubuntu、CentOS完全不是一回事——服务没起、端口没开、防火墙规则还跟你想的不一样。我见过太多人卡在“Connection refused”或者“Permission denied”上,折腾一晚上最后放弃,继续在虚拟机窗口里一个字一个字地敲。
这篇东西就是把我自己反复踩过的坑、验证过的配置流程,以及那些文档里不会写的细节,一次性讲清楚。核心就三件事:怎么把SSH服务跑起来、怎么让防火墙放行、怎么让配置在重启后依然生效。听起来简单,但每一步都有坑。比如Kali Rolling版本默认不带SSH服务端,你得先装;比如UFW和iptables在Kali里的默认策略跟Debian系其他发行版有微妙差异;再比如你改了sshd_config之后忘了检查语法,服务直接起不来,连报错都看不懂。
适合谁看?如果你是刚接触Kali的新手,照着做能少走两小时弯路;如果你已经用过SSH但总在防火墙这关卡住,这里有针对Kali的排查链路;如果你是要在实验环境里批量配置多台Kali,后面也有可复用的配置模板和批量操作思路。我不讲那些“SSH是加密远程登录协议”的教科书定义,直接上操作、上原理、上我踩过的坑。
2. Kali里SSH服务的安装与首次启动
2.1 先确认你的Kali到底有没有SSH服务端
很多人上来就systemctl start ssh,然后报错“Unit ssh.service not found”。这不是命令错了,是Kali默认根本没装SSH服务端。Kali的定位是渗透测试发行版,默认只装了SSH客户端(让你去连别人),服务端(让别人连你)需要手动安装。这个设计逻辑跟Ubuntu Server完全相反,所以习惯Ubuntu的人第一次用Kali会懵。
确认方法很简单,两条命令:
# 查看ssh服务端是否安装 dpkg -l | grep openssh-server # 查看ssh客户端是否安装(这个默认一定有) dpkg -l | grep openssh-client如果第一条命令没有任何输出,说明服务端没装。第二条命令应该能看到openssh-client的包信息。这里有个细节:Kali Rolling版本在2020年之后的镜像里,连客户端都可能精简掉,但大多数场景下客户端是保留的,因为渗透测试经常要SSH连靶机。
注意:不要用
apt install ssh这个命令。ssh是一个元包,在不同发行版里指向不同东西。在Kali里直接装openssh-server最稳妥,避免装错包。
2.2 安装openssh-server的正确姿势
安装本身不复杂,但有几个前置动作容易被忽略。首先更新源,Kali的源如果没配好,安装会失败或者装到旧版本:
sudo apt update sudo apt install openssh-server -y装完之后,系统会自动生成主机密钥(host keys),这些密钥在/etc/ssh/目录下,文件名类似ssh_host_rsa_key、ssh_host_ecdsa_key。如果你之前手动删过这些文件,或者从别的机器克隆了Kali镜像,密钥可能冲突,导致客户端连接时报“Host key verification failed”。解决办法是删掉/etc/ssh/ssh_host_*然后重新生成:
sudo rm /etc/ssh/ssh_host_* sudo dpkg-reconfigure openssh-server这个dpkg-reconfigure命令会重新跑一遍配置脚本,自动生成新的主机密钥。我试过在克隆的虚拟机里直接启动SSH,客户端连上去报密钥不匹配,排查了半天才发现是克隆导致密钥重复。这个坑在批量部署Kali虚拟机的时候特别常见。
2.3 启动服务并设置开机自启
装完之后,SSH服务默认可能是disabled状态。Kali用的是systemd,所以操作很标准:
# 启动服务 sudo systemctl start ssh # 设置开机自启 sudo systemctl enable ssh # 查看状态 sudo systemctl status ssh状态输出里看到active (running)就说明服务跑起来了。但这里有个隐藏问题:Kali在某些版本里,ssh.service和ssh.socket是两套机制。如果你用systemctl status ssh看到的是socket激活模式,那服务可能不是常驻的,而是按需启动。对于实验环境,我建议统一用ssh.service,避免socket模式带来的端口监听延迟。
检查方法:
sudo systemctl is-enabled ssh sudo systemctl is-active ssh两个命令分别返回enabled和active才算配置到位。如果is-enabled返回disabled,即使当前跑着,重启后也会失效。
2.4 验证SSH是否真的在监听
服务状态显示running,不代表端口一定在监听。可能配置文件有语法错误,服务启动了但没绑定端口。用这条命令确认:
ss -tlnp | grep :22或者老一点的系统用netstat -tlnp | grep :22。输出里应该看到LISTEN状态和对应的进程名sshd。如果什么都没看到,说明服务虽然显示running,但实际没监听端口,这时候要去查/var/log/auth.log或者journalctl -u ssh看具体报错。
我遇到过一种情况:sshd_config里写了Port 2222,但防火墙只开了22,结果本地ss能看到2222在监听,但远程连不上。所以端口监听和防火墙放行是两件事,必须分开验证。
3. sshd_config里那些真正影响连接的参数
3.1 默认配置里哪些参数必须改
Kali的/etc/ssh/sshd_config默认配置其实挺保守的,但有几个参数在实际使用中会带来麻烦。我按重要性排个序:
| 参数 | 默认值 | 建议值 | 原因 |
|---|---|---|---|
| PermitRootLogin | prohibit-password | no | 禁止root直接登录,用普通用户+sudo |
| PasswordAuthentication | yes | 按需 | 实验环境可保留yes,生产环境建议no |
| PubkeyAuthentication | yes | yes | 密钥登录更安全,保留 |
| Port | 22 | 按需 | 改非标准端口可减少扫描噪音 |
| ListenAddress | 0.0.0.0 | 按需 | 多网卡时指定监听地址 |
PermitRootLogin这个参数特别值得说。Kali默认是prohibit-password,意思是root不能用密码登录,但可以用密钥。很多人改成yes图方便,结果实验环境被扫到就麻烦。我的建议是保持no,用普通用户登录后再sudo -i切root,多一步但安全很多。
3.2 改完配置必须做的语法检查
这是我最想强调的一点:改完sshd_config千万不要直接restart。先跑语法检查:
sudo sshd -t如果配置有问题,这条命令会直接告诉你哪一行错了。没有输出就说明语法OK。我见过太多人改完配置直接systemctl restart ssh,结果服务起不来,SSH断了,只能去虚拟机控制台救火。先检查再重启,这个习惯能省你很多时间。
检查通过后再重启:
sudo systemctl restart ssh重启后再次用ss -tlnp确认端口监听正常,然后用另一台机器或另一个终端尝试连接。不要关掉当前SSH会话再重连,万一新配置有问题,你至少还有一个活着的会话可以回滚。
3.3 密钥登录的配置细节
密码登录虽然方便,但在实验环境里经常被扫描器爆破。配密钥登录其实不复杂,但有几个细节容易漏。
生成密钥对(在客户端机器上操作):
ssh-keygen -t ed25519 -C "kali-lab"ed25519比RSA更短更快,现代系统都支持。生成后把公钥传到Kali上:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@kali-ip如果ssh-copy-id不可用,手动追加也行:
cat ~/.ssh/id_ed25519.pub | ssh user@kali-ip "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"这里权限很关键。~/.ssh必须是700,authorized_keys必须是600。权限不对的话,SSH会静默忽略密钥,只让你输密码,而且不报错。我排查过好几次“密钥明明传了但还是要密码”的问题,最后都是权限不对。
服务端这边,确认sshd_config里:
PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys改完记得sshd -t检查再重启。
3.4 监听端口和地址的取舍
默认监听0.0.0.0:22,意思是所有网卡的所有IP的22端口都接受连接。在实验环境里,如果你的Kali有多张网卡(比如NAT一张、Host-Only一张),可能只想让Host-Only那张接受SSH。这时候改ListenAddress:
ListenAddress 192.168.56.10 Port 22这样只有指定IP的22端口监听,NAT网卡那边就连不上了。这个配置在隔离实验环境里很有用,避免暴露到不该暴露的网络。
改端口的话,注意SELinux(Kali默认没开)和防火墙都要同步改。我一般不建议改端口,因为Kali的实验环境通常在内网,改端口带来的安全收益有限,反而增加配置复杂度。如果确实要改,记得sshd -t检查,防火墙规则同步更新。
4. Kali防火墙的默认状态与放行策略
4.1 Kali默认防火墙到底开没开
这是最容易让人困惑的地方。Kali默认没有启用任何防火墙。ufw status会显示inactive,iptables -L会显示空规则链。也就是说,刚装好的Kali,所有端口都是开放的,SSH只要服务跑起来就能连。
但问题在于,很多人从别的教程里抄了ufw enable,结果把自己关在外面。因为UFW默认策略是deny incoming,你一启用,所有入站连接全断,包括你正在用的SSH。如果你是在远程连Kali,启用UFW的瞬间你就掉线了。
所以第一步永远是:先确认防火墙状态,再决定要不要动它。
sudo ufw status verbose sudo iptables -L -n如果ufw是inactive,iptables是空规则,那SSH连不上就不是防火墙的问题,去查服务监听和网络连通性。
4.2 UFW的规则配置与SSH放行顺序
如果你确实需要启用防火墙(比如Kali放在公网可访问的环境),那顺序必须是:先放行SSH,再启用UFW。
# 先放行SSH端口 sudo ufw allow 22/tcp # 再启用 sudo ufw enable如果SSH改过端口,比如2222:
sudo ufw allow 2222/tcp sudo ufw enable启用后检查规则:
sudo ufw status numbered输出里应该看到22/tcp ALLOW IN Anywhere。如果没看到,说明规则没生效,检查是不是先enable后allow了。
注意:如果你已经启用了UFW并且SSH断了,别慌。去虚拟机控制台(VMware/VirtualBox的窗口)登录,然后
sudo ufw allow 22/tcp,再sudo ufw reload。如果控制台也进不去,重启进恢复模式,ufw disable。
4.3 iptables直接操作的场景
有些实验环境要求用iptables而不是UFW,比如你要模拟特定网络策略。iptables的规则是即时生效的,但默认重启后丢失。要持久化得用iptables-persistent:
sudo apt install iptables-persistent -y放行SSH的规则:
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT第二条规则很重要,它允许已建立的连接继续通信。没有这条,你SSH连上去之后,回包可能被拦,表现为能连上但卡死。
保存规则:
sudo netfilter-persistent save这个命令会把当前iptables规则写到/etc/iptables/rules.v4,重启后自动加载。
4.4 UFW和iptables的优先级关系
这里有个容易搞混的点:UFW底层就是iptables的前端。你ufw allow之后,实际是在iptables里插了规则。如果你同时手动改iptables,可能跟UFW的规则冲突。我的建议是二选一,要么全用UFW,要么全用iptables,不要混着来。
如果非要混用,记住UFW的规则链在iptables里是ufw-user-input,你手动加的规则如果在INPUT链里排在UFW之前,可能覆盖UFW的策略。排查的时候用iptables -L -n --line-numbers看规则顺序,顺序错了就全乱。
5. 从连接失败到连通的完整排查链路
5.1 第一层:网络通不通
SSH连不上,先别急着查SSH配置。第一步永远是确认网络层通不通:
ping kali-ip如果ping不通,后面都不用查了。检查Kali的IP、网卡模式(NAT/桥接/Host-Only)、宿主机防火墙。虚拟机环境里最常见的是网卡模式选错,比如Kali是NAT模式,但你从宿主机用Host-Only的网段去连,肯定不通。
ping通了但SSH连不上,继续下一步。
5.2 第二层:端口开没开
在Kali本机确认端口监听:
ss -tlnp | grep :22有输出说明服务在监听。没输出说明SSH服务没跑起来,回去查systemctl status ssh和journalctl -u ssh。
本机确认监听正常后,从客户端测端口连通性:
nc -zv kali-ip 22或者用telnet kali-ip 22。如果显示Connection refused,说明端口没监听或者防火墙REJECT。如果显示Connection timed out,说明防火墙DROP或者网络中间有设备拦截。
5.3 第三层:防火墙规则有没有拦
在Kali上查防火墙:
sudo ufw status verbose sudo iptables -L -n -v重点看INPUT链的默认策略和规则。如果默认策略是DROP且没有放行22的规则,那就是防火墙拦了。加规则:
sudo ufw allow 22/tcp或者iptables:
sudo iptables -I INPUT -p tcp --dport 22 -j ACCEPT注意-I是插入到链首,-A是追加到链尾。如果前面有DROP规则,-A加的规则永远匹配不到,必须用-I。
5.4 第四层:SSH服务本身的认证问题
端口通了,但连接时报Permission denied或者Authentication failed,那就是认证层的问题。常见原因:
- 密码错了(大小写、键盘布局)
- 用户不存在或被锁定
sshd_config里AllowUsers或DenyUsers限制了- 密钥权限不对
- PAM模块拦截
排查方法:在Kali上看/var/log/auth.log,里面会记录每次登录尝试的详细原因。比如Failed password for invalid user说明用户名错了,Authentication refused: bad ownership or modes说明密钥文件权限不对。
5.5 第五层:那些诡异的“能连上但卡住”
有一种情况最折磨人:SSH能连上,输入密码后卡住,或者连上后命令执行很慢。这通常是DNS反向解析导致的。sshd_config里有个UseDNS参数,默认可能是yes,服务端会尝试反向解析客户端IP,如果DNS不可用,就会卡几十秒。
解决办法:
UseDNS no GSSAPIAuthentication no改完sshd -t检查再重启。这两个参数在实验环境里建议都关掉,能显著提升连接速度。
6. 让配置在重启后依然生效的持久化方案
6.1 SSH服务自启的确认
systemctl enable ssh只是设置了开机自启,但如果你用的是ssh.socket模式,可能行为不一样。确认方法:
systemctl list-unit-files | grep ssh输出里ssh.service应该是enabled。如果是disabled,重新enable。另外检查有没有ssh.socket被enable了,如果两个都enable,可能冲突。建议只保留ssh.service:
sudo systemctl disable ssh.socket sudo systemctl enable ssh.service6.2 防火墙规则的持久化
UFW的规则默认就是持久的,ufw enable之后规则会写到/etc/ufw/下的配置文件,重启自动加载。但有个例外:如果你手动改了/etc/ufw/user.rules但没ufw reload,重启后可能不生效。保险做法是每次改完规则跑一次:
sudo ufw reloadiptables的话,前面说了用netfilter-persistent save。但注意,如果你同时装了UFW和iptables-persistent,重启时可能互相覆盖。建议只用一个。
6.3 配置文件备份与版本管理
sshd_config改多了容易乱,建议改之前备份:
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak如果实验环境有多台Kali,可以把调好的配置存到版本控制里,批量分发。我自己的做法是维护一个sshd_config模板,新机器装好SSH后直接覆盖,然后sshd -t检查,重启服务。这样能保证所有机器的配置一致,排查问题的时候少一个变量。
6.4 重启后的验证清单
每次重启Kali后,按这个清单过一遍:
systemctl status ssh— 服务是否runningss -tlnp | grep :22— 端口是否监听sudo ufw status— 防火墙规则是否加载- 从客户端
nc -zv kali-ip 22— 端口是否可达 - 实际SSH登录一次 — 认证是否正常
这五步走完,基本能覆盖99%的“重启后连不上”问题。我见过太多人重启后直接连,连不上就慌,其实按清单一步步查,问题很快定位。
7. 多场景下的配置取舍与经验心得
7.1 虚拟机NAT模式下的SSH配置
NAT模式下,Kali的IP是VMware/VirtualBox分配的,宿主机不能直接访问,需要配端口转发。以VirtualBox为例,在虚拟机设置里加一条NAT端口转发规则:宿主端口2222,虚拟机端口22。然后从宿主机ssh -p 2222 user@127.0.0.1就能连上。
这种场景下,Kali内部的防火墙通常不用动,因为NAT转发是在虚拟化层做的,流量到了Kali内部已经是本地连接。但如果你在Kali里启用了UFW且没放行22,照样连不上。所以NAT模式下,SSH服务跑起来+UFW放行22,两个条件缺一不可。
7.2 桥接模式下的局域网访问
桥接模式下,Kali跟宿主机在同一局域网,IP是路由器分配的。这种场景最方便,同网段任何机器都能SSH连。但要注意:
- 如果局域网有DHCP,Kali的IP可能变,建议配静态IP或者在路由器上绑MAC
- 防火墙必须放行22,因为流量是从外部进来的
- 如果局域网有安全策略,可能拦截22端口,换个端口试试
桥接模式下我一般会改SSH端口到非标准值,减少被扫描的概率。虽然实验环境通常安全,但养成习惯没坏处。
7.3 多台Kali批量配置的思路
如果你要配多台Kali(比如实验集群),一台台手动改太慢。我的做法是写个简单的shell脚本,把sshd_config模板、防火墙规则、密钥分发都自动化。核心步骤:
- 用
sshpass或预置密钥做初始认证 - 分发
sshd_config模板 - 跑
sshd -t检查 - 重启服务
- 配置UFW规则
- 验证端口监听
这个脚本不需要多复杂,几十行就能搞定。关键是每步都要有错误检查,比如sshd -t失败就中止,不要盲目重启。
7.4 那些文档里不会写的细节
最后分享几个我踩过的坑:
坑一:sshd_config里的注释符号。#开头的行是注释,但有些参数默认值就是注释掉的。你改的时候如果直接在注释行后面加内容,比如#Port 22改成#Port 22然后另起一行写Port 2222,没问题。但如果你把#去掉改成Port 22,又没改端口号,那就跟默认一样。改配置的时候看清楚是注释还是生效行。
坑二:UFW的allow和limit。ufw allow 22是允许所有连接,ufw limit 22是限制连接频率(防爆破)。实验环境用allow就行,limit在某些扫描场景下会误拦。
坑三:SSH连接慢但能连上。除了UseDNS,还可能是GSSAPIAuthentication导致的。两个都关掉,连接速度立竿见影。
坑四:改了端口后ss -tlnp看不到。检查sshd_config里是不是有多个Port行,或者ListenAddress限制了。sshd -t能查出语法问题,但逻辑问题得自己看。
坑五:密钥登录突然失效。检查~/.ssh和authorized_keys权限,检查sshd_config里PubkeyAuthentication是不是被注释了,检查AuthorizedKeysFile路径对不对。这三个查完基本能解决。
这些细节在官方文档里要么一笔带过,要么分散在不同章节,实际用的时候得自己串起来。我写这篇就是想把这条链路一次性打通,让你在Kali上开SSH、配防火墙这件事上,不再卡壳。