一、问题背景与现象
很多刚接触渗透测试工具的开发者,都会在第一次启动Metasploit时碰到数据库初始化失败的报错——要么弹“PostgreSQL连接池耗尽”的红色提示,要么说“端口被占用”,折腾半天还是连不上数据库,根本没法用Metasploit的核心功能。我之前帮好几个朋友排查过这类问题,发现80%的人都是踩了操作习惯或者环境配置的坑,根本不是工具本身的大问题。
先给大家说下最常见的报错现象,方便对照:打开终端输入msfconsole启动Metasploit后,终端会输出类似这样的错误:
[-] Database initialization failed: Unable to connect to the database: PG::ConnectionBad: FATAL: connection limit exceeded for non-superusers
或者另一种端口占用的报错:
[-] Database initialization failed: Unable to connect to the database: PG::ConnectionBad: could not connect to server: Connection refused
Is the server running on host "localhost" (::1) and accepting
TCP/IP connections on port 5432?
could not connect to server: Connection refused
Is the server running on host "localhost" (127.0.0.1) and accepting
TCP/IP connections on port 5432?
碰到这俩报错,别慌,接下来一步步拆解解决。
二、核心问题分析
要解决问题,得先搞懂Metasploit和PostgreSQL的关系:Metasploit本身不带数据库,它的漏洞库、扫描结果、攻击记录这些数据,都存在一个叫PostgreSQL的数据库里。Metasploit启动时会自动找这个数据库,找不到或者连不上,就会报初始化失败。
那两个报错的本质是什么? 第一个“连接池耗尽”:简单说就是PostgreSQL数据库允许同时连的人数(或者说连接数)满了,Metasploit抢不到名额,连不进去。就像奶茶店的堂食座位全坐满了,新来的人只能等。 第二个“端口占用”:PostgreSQL默认用5432端口,要是这个端口被别的程序占了(比如你电脑上跑了另一个PostgreSQL服务,或者别的软件用了这个端口),Metasploit就找不到数据库的“门”,连不进去。
三、连接池耗尽的解决步骤
3.1 先排查当前连接状态
碰到连接池耗尽,第一步要搞清楚现在有多少连接占着名额,哪些是没用的。我们用PostgreSQL自带的命令来查,首先得先连到PostgreSQL的控制台:
# 先切换到postgres用户(不同系统可能略有差异,比如Ubuntu是sudo -u postgres psql,CentOS是su - postgres -c "psql")
sudo -u postgres psql
连进去后,执行查询命令看所有连接:
-- 查看当前所有PostgreSQL连接,按用户名、进程ID分组统计
SELECT usename, pid, client_addr, state FROM pg_stat_activity;
执行后会看到类似的结果:
usename | pid | client_addr | state
----------+------+-------------+--------
postgres | 1234 | 127.0.0.1 | idle
msf | 5678 | 127.0.0.1 | idle
msf | 9012 | 127.0.0.1 | idle
这里的idle状态就是没用的连接,就像有人占着奶茶店座位玩手机,不买东西也不走。
3.2 释放闲置连接
找到没用的连接后,我们可以手动杀掉它们,释放名额。比如上面结果里的pid是5678和9012的连接,都是idle状态,我们执行:
-- 杀掉指定pid的连接,注意把<pid>换成你查到的实际数字
SELECT pg_terminate_backend(<pid>);
比如杀掉5678这个连接:
SELECT pg_terminate_backend(5678);
执行后会返回t,表示杀掉成功。如果要批量杀所有闲置的msf用户连接,可以执行:
-- 杀掉所有usename为msf、状态为idle的连接
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE usename = 'msf' AND state = 'idle';
释放完连接后,再启动Metasploit,大概率就能正常连了。
3.3 从根源解决:修改最大连接数
如果每次启动Metasploit都碰到连接池耗尽,说明默认的最大连接数太小了,我们可以直接修改PostgreSQL的配置,把名额调大。 首先找到PostgreSQL的配置文件,不同系统路径不一样:
- Ubuntu/Debian系统:
/etc/postgresql/<版本号>/main/postgresql.conf(比如版本号是14,路径就是/etc/postgresql/14/main/postgresql.conf) - CentOS/RHEL系统:
/var/lib/pgsql/<版本号>/data/postgresql.conf - macOS(用Homebrew安装的):
/usr/local/var/postgres/postgresql.conf
用文本编辑器打开这个文件,比如用vim:
# 以Ubuntu系统为例,把<版本号>换成你实际的版本号
sudo vim /etc/postgresql/<版本号>/main/postgresql.conf
打开后找max_connections这一行,默认可能是100,我们改成200(足够Metasploit用了):
# 把原来的max_connections = 100改成下面的,注意去掉行首的#(如果有的话)
max_connections = 200
改完保存退出,然后重启PostgreSQL服务生效:
# Ubuntu系统的重启命令
sudo systemctl restart postgresql
# CentOS系统的重启命令
sudo systemctl restart postgresql-14.service # 把14换成你的版本号
# macOS的重启命令
brew services restart postgresql
四、端口占用的解决步骤
4.1 先确认端口被谁占了
碰到端口占用,第一步要搞清楚5432端口被哪个程序占了,我们用系统自带的命令查:
# Linux/macOS系统用这个命令,查占用5432端口的进程
lsof -i :5432
执行后会看到类似结果:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 1234 test 10u IPv6 12345 0t0 TCP localhost:5432 (LISTEN)
这里的COMMAND是java,PID是1234,说明是一个Java程序占了5432端口。
4.2 两种解决方式:关进程或改端口
4.2.1 方式一:关掉占用端口的进程
如果这个占用5432端口的程序不重要,我们可以直接杀掉它,释放端口。执行:
# 把<pid>换成你查到的实际进程ID
kill -9 <pid>
比如上面查到的PID是1234,就执行:
kill -9 1234
杀掉后再查端口:
lsof -i :5432
如果没有结果,说明端口已经释放了,再启动Metasploit就正常了。
4.2.2 方式二:改Metasploit的数据库端口
如果占用5432端口的程序很重要,不能杀,那我们可以改Metasploit的配置,让它用别的端口连PostgreSQL。
首先得先改PostgreSQL的监听端口,还是打开之前的postgresql.conf配置文件,找port这一行:
# 把原来的port = 5432改成别的端口,比如5433
port = 5433
改完保存退出,重启PostgreSQL服务生效。
然后改Metasploit的数据库配置文件,Metasploit的配置文件路径是~/.msf4/database.yml,用文本编辑器打开:
vim ~/.msf4/database.yml
打开后会看到类似的内容:
development:
adapter: postgresql
database: msf
username: msf
password: msf
host: localhost
port: 5432
pool: 5
timeout: 5
把port改成5433:
development:
adapter: postgresql
database: msf
username: msf
password: msf
host: localhost
port: 5433 # 改成和PostgreSQL一致的端口
pool: 5
timeout: 5
改完保存退出,再启动Metasploit,就会用5433端口连数据库了。
五、应用场景、优缺点与注意事项
5.1 应用场景
这两个问题的解决方法,主要适用于以下场景:
- 第一次安装Metasploit后启动失败,碰到连接池耗尽或端口占用;
- 之前能正常用Metasploit,突然启动报错,排查到是连接池或端口问题;
- 自己的电脑上同时跑多个需要用PostgreSQL的程序(比如Metasploit和一个Java开发的项目),碰到端口冲突;
- 批量启动多个Metasploit实例(比如自动化测试时),碰到连接池不够用。
5.2 技术优缺点
连接池相关方法的优缺点
优点:手动杀闲置连接见效快,适合临时解决问题;修改最大连接数从根源解决,适合长期使用; 缺点:手动杀连接如果误杀了正在用的连接,可能会导致别的程序出错;改最大连接数如果改得太大,会占用更多的系统内存(每个连接都会占一点内存)。
端口相关方法的优缺点
优点:杀占用进程的方法操作简单,适合临时解决;改端口的方法不会影响别的程序,适合长期使用; 缺点:杀进程可能会导致别的程序丢失数据(比如正在运行的Java程序如果有未保存的数据,被杀掉后会丢失);改端口需要改两个配置文件,操作稍微麻烦一点。
5.3 注意事项
- 改PostgreSQL配置文件时,一定要备份原文件,比如改之前先执行
sudo cp /etc/postgresql/<版本号>/main/postgresql.conf /etc/postgresql/<版本号>/main/postgresql.conf.bak,万一改坏了可以恢复; - 手动杀PostgreSQL连接时,一定要确认是
idle状态的连接,不要杀active状态的连接(active状态是正在用的); - 如果是在服务器上操作,改端口或杀进程前,一定要通知相关的开发或运维人员,避免影响线上业务;
- Metasploit的数据库配置文件
database.yml里的密码,一定要和PostgreSQL里msf用户的密码一致,不然就算端口对了也连不上。
六、文章总结
Metasploit的数据库初始化失败,本质上就是和PostgreSQL的连接出了问题,要么是连接名额满了,要么是端口被占了。碰到问题时,先对照报错现象判断是哪种情况,再按步骤排查:连接池耗尽就先杀闲置连接,再改最大连接数;端口占用就先查谁占了,要么杀进程要么改端口。
很多新手碰到这类问题会觉得是工具难用,其实只要搞懂背后的逻辑,一步步排查,很快就能解决。另外,平时用Metasploit时,用完后正常退出(不要直接关终端),可以避免产生闲置连接;如果要同时跑多个需要PostgreSQL的程序,提前规划好端口,就能减少这类问题的发生。
Comments