我有两台服务器,它们在同一个网络上安装了相对较新的 CentOS 9 Stream。我可以在它们之间 ping 和 ssh,因此可以证明基本的连接。据我所知,服务器 A 已打开端口 1883 (mqtt),我有一个简单的 python 测试服务器正在监听。但是当我尝试从服务器 B 访问端口 1883 时,我收到“连接被拒绝”的提示。
[serverA]$ sudo firewall-cmd --list-all
public (active)
target: default
icmp-block-inversion: no
interfaces: enp1s0f1
sources:
services: cockpit dhcpv6-client mqtt ssh
ports: 1883/tcp 9001/tcp
protocols:
forward: yes
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
[serverA]$ sudo netstat -tunlp
...
tcp 0 0 0.0.0.0:1883 0.0.0.0:* LISTEN 1497041/python
...
_
[serverB]$ curl -g -6 "http://[<<serverA ipv6>>]:1883"
curl: (7) Failed to connect to <<serverA ipv6>> port 1883: Connection refused
[serverB]$ nc -z -v -w5 <<serverA ipv6>> 1883
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Connection refused.
从对该错误的初步研究中,我可以检查:
- 根据 Firewalld,端口 1883 在 serverA 上是开放的(明确地并通过 mqtt 服务)
- serverA 正在积极监听 0 0.0.0.0:1883(不是 127.0.0.1 等)
- 据我所知,没有额外的防火墙硬件影响两台服务器之间的流量
我还能测试什么?不确定 iptables 是否有任何作用,因为我使用的是 Firewalld
编辑并了解更多背景信息:
因此我记录了我如何解决这个问题,但我想提供一些可能对未来旅行者有帮助的背景信息。
我试图与正在通过 docker compose 运行的 mosquitto mqtt 代理进行通信。为了从方程中取出一个变量,我直接从操作系统中使用了一个简单的测试 python 服务器。真正的问题是 mosquitto.conf 中的这一行:
listener 1883 0.0.0.0
尾随的 0.0.0.0 无意中将 mosquitto 设置为仅监听 ipv4。尽管 mosquitto 文档的 Listener 部分没有关于此问题的具体信息,但 socket_domain 部分却说明了这一点: https://mosquitto.org/man/mosquitto-conf-5.html
如果您想要同时支持 IPv4 和 IPv6,那么请不要使用 socket_domain 选项。
所以我所要做的只是将该行改为:
listener 1883
然后 mosquitto 神奇地开始监听 ipv4 和 ipv6
答案1
好吧,我对 ipv6 和 ipv4 了解不够。我注意到端口 22 可以工作,但 1883 不可以:
[serverB]$ nmap -6 -Pn -p 1883 <<serverA ipv6>>
PORT STATE SERVICE
1883/tcp closed mqtt
[serverB]$ nmap -6 -Pn -p 22 <<serverA ipv6>>
PORT STATE SERVICE
22/tcp open ssh
然后我查看了 serverA 上的监听端口,发现 1883 被列为 tcp,而 22 被列为 tcp6:
[serverA]$ sudo netstat -tunlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:1883 0.0.0.0:* LISTEN 10077/python
...
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1602/sshd: /usr/sbi
...
tcp6 0 0 :::22 :::* LISTEN 1602/sshd: /usr/sbi
...
因此,我修改了测试服务器脚本,使其监听 tcp ipv6。旧的 ipv4 专用服务器测试脚本:
import socket
# Create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Define the port on which you want to connect
port = 1883
# Bind to the port
s.bind(('', port))
# Put the socket into listening mode
s.listen(5)
print('Socket is listening')
# A forever loop until we interrupt it or an error occurs
while True:
# Establish connection with client
c, addr = s.accept()
print('Got connection from', addr)
# Send a thank you message to the client
c.send(b'Thank you for connecting')
# Close the connection with the client
c.close()
新的 ipv6 服务器脚本:
import socket
# Create a socket object
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
# Define the port on which you want to connect
port = 1883
# Bind to the port
s.bind(('::', port))
# Put the socket into listening mode
s.listen(5)
print('Socket is listening')
# A forever loop until we interrupt it or an error occurs
while True:
# Establish connection with client
c, addr = s.accept()
print('Got connection from', addr)
# Send a thank you message to the client
c.send(b'Thank you for connecting')
# Close the connection with the client
c.close()
我现在有一个使用 ipv6 监听端口 1883 的进程:
tcp6 0 0 :::1883 :::* LISTEN 10177/python
我可以使用端口 1883 从服务器 B 连接到服务器 A