个人微信:_iihero
CSDN: iihero
墨天轮:https://www.modb.pro/u/16258 (Sean)
pgfans: iihero
前言
前几天,碰到有人问起一个PG配置完成以后,无论怎么改,都不能通过另一台机器访问的问题。
该问题直接上图:
他们的内网,分两个网段,testA和testB位于192.168.40.*, 而testC位于192.168.30.*。现在的问题是, testA和testB可以访问testC,反过来则不行,一直hang在那里。
psql -h192.168.40.16 -p5432 -Upostgres
直接超时
分析过程
光看前边的描述,有一个本能的直觉,就是testA和testB提供的PG服务端口,没有成功的暴露出来,那么到底是PG本身的hba配置不对呢,还是操作系统有防火墙的相关配置,没有将相应的端口开放出去?
如何排错?
因为都相当于是远程提问,无法直接测试。所以,尽量的多提供些上下文,便能得到更多的信息。
1、testA, testB可以与testC相互ping
2、甚至用ssh也可以登录正常。
3、hang出现的现象是:
$ psql -h192.168.40.16 -p5432 -Upostgrespsql
:error: could not connect to server
: Connection timed outIs the server running on host "192.168.40.16" and acceptingTCP/IP connections on port 5432?
而testA使用访问testC,则直接能连接成功。
postgres@testA pg16data]$ psql -h192.168.30.18 -p5432 -Upostgres
Password for user postgres:
附加的上下文信息
让提问的朋友提供testA/B/C的hba及主配置postgresql.conf相关配置项,大概是这样的:
hba.conf
testC的配置如下:
testA/testB:
testB:
postgresql.conf主配置
再看主配置文件里头的监听地址信息:
postgres=#\dconfig listen_addresses
List of configuration parameters
Parameter | Value
-----------------------------------------
listen addresses | *,localhost
(1 row)
postgres=#
又给出了testC的详细的规则信息:
防火墙及网关
甚至防火墙的相关配置也给出了:
网关信息:
从上边的配置来看,pg_hba.conf并没有刻意去阻塞访问,相反,testA, testB都开放了所有IPV4的访问,使用md5方法来验证用户密码。
host all all 0.0.0.0/0 md5
然后,listenning address为 *,localhost,那相当于是对所有IP都开放,包括IPV6。虽然这里头的"localhost"项完全是多余的。但也不会造成错误。注意,此处真正起作用的是前边的"*", 如果有时间,你可以自行验证。如果你设置的是"localhost, *",那么真正起作用的是localhost。
具体验证
一般而言,如果只是hba配置文件里头没有对应项或者对应项不通过,都不会是hang的错误,应该是很快就有一个错误信息,表示没有认证项。
例如:
pg_hba.conf文件内容如下:
local all all reject
host all all 127.0.0.1/32 reject
host all all samenet scram-sha-256
如果应用此规则 ,表示本机的unixsocket或者127.0.0.1,都拒绝访问。
[18:00:38-postgres@centos1:/var/lib/pgsql/14/data]$ pg_ctl reload
server signaled
[18:00:40-postgres@centos1:/var/lib/pgsql/14/data]$ psql
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5555" failed: FATAL: pg_hba.conf rejects connection for host "[local]", user "postgres", database "postgres", no encryption
[18:01:49-postgres@centos1:/var/lib/pgsql/14/data]$ psql -h 127.0.0.1 -U postgres
psql: error: connection to server at "127.0.0.1", port 5555 failed: FATAL: pg_hba.conf rejects connection for host "127.0.0.1", user "postgres", database "postgres", no encryption
你看看,它是直接返回reject connection的信息,而不是hang在那里。
而且这个时候,你用telnet是能正常访问的。
[18:01:58-postgres@centos1:/var/lib/pgsql/14/data]$ telnet 127.0.0.1 5555
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
如果是postgresql.conf中地址项配置错误,错误信息应该是:
cat >>postgresql.conf<<EOF
> listen_addresses = '127.0.0.1'
> EOF
pg_ctl restart
psql -h 192.168.0.6
[18:44:07-postgres@centos1:/var/lib/pgsql/14/data]$ psql -h 192.168.0.6
psql: error: connection to server at "192.168.0.6", port 5555 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?
这里也会直接报连接错误,而不是hang/超时。
验证方法一:telnet <port>
其实,到了这一步,基本上在testC主机上,应用telnet <IP of testA> ,如果能连通,则意味着是pg_hba.conf配置出错。如果telnet本身就hang,意味着有别的防火墙软件在阻塞着目标端口的访问。
在windows 10上,可能telnet客户端命令并没有安装 。安装 一下即可。不贴图了。
安装步骤:程序和功能 -》 启用和关闭windows功能 -》 TELNET客户端。
验证方法二:使用NC客户端和服务器端探测
上边不是对testC访问testA或B访问不了,不能完全确信是否是PG本身,还是防火墙造成的吗?
一种是直接使用nc命令连接目标端口:5555
[21:16:24-postgres@centos1:/var/lib/pgsql]$ nc -v 192.168.0.6 5555
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 192.168.0.6:5555.
这里能连接,意味着pg的配置肯定没有问题。再深入一步,
可以把testA的pg端口给停了,假定端口是5556. 然后在testA上启一个5555的nc服务。再用nc客户端来连接:
服务器:
nc -lv 5566 &
[2] 1749
[21:17:36-postgres@centos1:/var/lib/pgsql]$ Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Listening on :::5566
Ncat: Listening on 0.0.0.0:5566
客户端(能连上,无防火墙):
[21:17:55-postgres@centos1:/var/lib/pgsql]$ nc -v 192.168.0.6 5566
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to 192.168.0.6:5566.
Ncat: Connection from 192.168.0.6.
Ncat: Connection from 192.168.0.6:52862.
客户端(连不上,有防火墙):
[21:17:55-postgres@centos1:/var/lib/pgsql]$ nc -v 192.168.0.6 5566
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connection refused.
验证方法三:使用TCP device来访问
-- 无法连接
[21:17:55-postgres@centos1:/var/lib/pgsql]$ echo >/dev/tcp/192.168.0.6/5566
-bash: connect: Connection refused
-bash: /dev/tcp/192.168.0.6/5566: Connection refused
--连接成功
[18:39:32-postgres@centos1:/var/lib/pgsql/14/data]$ echo >/dev/tcp/192.168.0.6/5555
(此处没有任何错误提示)
验证方法四:使用ssh相关命令带-v -p开关
连接失败的安例:
ssh -v 192.168.0.6 -p 5566
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 58: Applying options for *
debug1: Connecting to 192.168.0.6 [192.168.0.6] port 5566.
debug1: connect to address 192.168.0.6 port 5566: Connection refused
连接成功的安例:
ssh -v 192.168.0.6 -p 5555
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 58: Applying options for *
debug1: Connecting to 192.168.0.6 [192.168.0.6] port 5555.
debug1: Connection established.
debug1: identity file /var/lib/pgsql/.ssh/id_rsa type 1
debug1: key_load_public: No such file or directory
debug1: identity file /var/lib/pgsql/.ssh/id_rsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /var/lib/pgsql/.ssh/id_dsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /var/lib/pgsql/.ssh/id_dsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /var/lib/pgsql/.ssh/id_ecdsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /var/lib/pgsql/.ssh/id_ecdsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /var/lib/pgsql/.ssh/id_ed25519 type -1
debug1: key_load_public: No such file or directory
debug1: identity file /var/lib/pgsql/.ssh/id_ed25519-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_7.4
ssh_exchange_identification: Connection closed by remote host
最后结局:
最后经过证实,testA和testB上的端口对不是同网段的IP被设置了阻断访问,使用的是深信服的防火墙服务。看来,他们运维在这一块做的还是比较严谨的。使用哪个,才开放哪个。访问逐段逐层放开,基本符合产品环境的安全使用原则。
总结:
关于网络排错,可以在结合postgresql.conf/pg_hba.conf的基础上,使用上边介绍的四种方法进行诊断与排错。一般情况下,PG本身的配置不会导致连接hang的错误,要么是能连上,要么是拒绝连接。很快有响应。
上述四种方法使用起来都很便利。
telnet host port
NC服务器和客户端命令搭配
TCP device: echo >/dev/tcp/{IP}/{port}
ssh -v {IP} -p {port}
说得更直白一些,上边的诊断手段,还是来自于操作系统本身的网络通信相关诊断工具的应用。数据库本身的运维切不可完全抛开操作系统本身的一些基础维护独立存在,两者结合起来,才能发挥出应有的效果。
往期导读:
1. PostgreSQL中配置单双向SSL连接详解
2. 提升PSQL使用技巧:PostgreSQL中PSQL使用技巧汇集(1)
3. 提升PSQL使用技巧:PostgreSQL中PSQL使用技巧汇集(2)
4. PostgreSQL SQL的基础使用及技巧
5. PostgreSQL开发技术基础:过程与函数
6. PostgreSQL中vacuum 物理文件truncate发生的条件
7. PostgreSQL中表的年龄与Vacuum的实验探索:Vacuum有大用
8. PostgreSQL利用分区表来弥补AutoVacuum的不足
9. 也聊聊PostgreSQL中的空间膨胀与AutoVacuum
10. 正确理解SAP BTP中hyperscaler PG中的IOPS (AWS篇)