LHIDC

FreeBSD服务器无法访问时,如何从DNS解析与防火墙端口逐层定位

本文面向排查FreeBSD服务器访问失败的运维人员,介绍如何依次验证DNS记录、IPv4与IPv6入口、TCP端口监听、PF或IPFW规则、反向代理及应用状态,并结合抓包、规则计数和日志建立完整的故障证据链。

FreeBSD服务器无法访问时,如何从DNS解析与防火墙端口逐层定位

“网页打不开”并不等于服务器负载过高。DNS 返回错误、域名指向旧地址、IPv6 记录不可达、端口没有监听、防火墙丢弃连接、反向代理无法连接上游,都可能表现为超时或访问失败。CPU、内存和带宽指标只能描述资源状态,不能直接证明请求已经到达 FreeBSD 服务器。

有效的定位方法是把一次访问拆成 DNS 解析、网络入口、TCP 端口、防火墙、代理、应用响应 六个阶段,并为每个阶段寻找可验证的证据。通常应先在外部客户端确认域名和端口,再到服务器检查监听与数据包,最后检查代理和应用日志,避免一开始就修改防火墙或重启服务。

先把“无法访问”转换成可判断的现象

不同错误对应的故障范围并不相同。排查前应记录客户端看到的原始错误,而不是只描述“访问不了”。

客户端现象 通常说明什么 不能直接证明什么
NXDOMAIN 查询结果认为域名不存在 不能证明服务器是否正常
SERVFAIL 递归或权威DNS处理失败 不一定是服务器网络故障
Connection timed out TCP连接未在等待时间内建立 不能直接判断是防火墙还是路由问题
Connection refused 目标主机返回拒绝,常见于端口未监听 不表示DNS一定正确
TLS证书错误 已到达某个TLS服务,但证书、SNI或时间可能异常 不代表后端应用正常
HTTP 404 已有HTTP服务响应,但站点或路由未匹配 不一定是目标业务应用返回
HTTP 502 代理已响应,但连接上游应用失败或收到异常响应 通常不是客户端到代理端口被阻断
HTTP 504 代理等待上游超时 不能仅凭状态码判定上游负载过高

如果客户端安装了 curl,可以将访问耗时拆分为多个阶段:

curl -sk -o /dev/null \
  -w 'dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} first_byte=%{time_starttransfer} code=%{http_code}\n' \
  https://example.com/

其中:

  • time_namelookup 表示DNS解析完成的累计时间。
  • time_connect - time_namelookup 大致对应TCP连接阶段。
  • time_appconnect - time_connect 大致对应TLS握手阶段。
  • time_starttransfer - time_appconnect 可用于观察HTTPS服务开始返回内容前的等待时间。

这些值只能帮助确定等待发生在哪一段,不能单独证明根因。例如首字节等待较长,既可能是应用处理慢,也可能是代理排队、上游网络等待或外部依赖阻塞。示例中的 -k 会忽略证书校验,只适合临时诊断,不应作为正式健康检查参数。

DNS要检查“解析结果”,不只是检查“能否解析”

域名能返回地址,不代表地址一定正确。DNS阶段需要确认以下内容:

  • A记录是否指向实际IPv4入口。
  • AAAA记录是否存在,以及IPv6入口是否真的可用。
  • CNAME最终指向哪里,是否仍引用旧域名或旧平台。
  • 权威DNS与递归DNS结果是否一致。
  • 多个地址中是否只有部分节点可访问。
  • DNS变更后,客户端或递归服务器是否仍使用缓存结果。

在装有 drill 的环境中,可以分别检查记录类型:

drill example.com A
drill example.com AAAA
drill example.com CNAME
drill example.com NS

如需直接查询权威DNS,可先从NS记录中取得服务器名称,再执行:

drill @ns1.example-dns.com example.com A
drill @ns1.example-dns.com example.com AAAA

如果系统没有 drill,也可以使用已安装的 dig 或 host。不要为了排障直接更改域名记录,应先保存当前记录值、TTL和变更时间。

特别检查IPv4与IPv6差异

一种常见情况是A记录可用,但AAAA记录指向未配置服务或未放行端口的IPv6地址。部分客户端优先尝试IPv6,于是会出现“有的网络能访问,有的网络超时”。

可以从外部客户端分别测试:

curl -4Iv --connect-timeout 5 https://example.com/
curl -6Iv --connect-timeout 5 https://example.com/

如果IPv4成功而IPv6失败,应继续检查:

  • AAAA记录是否仍有必要保留。
  • FreeBSD服务器是否配置了对应IPv6地址。
  • 服务是否监听IPv6端口。
  • PF、IPFW及上游网关是否允许IPv6入站。
  • 默认IPv6路由是否正确。

删除AAAA记录不是唯一处理方式。如果业务需要IPv6,应修复监听、防火墙和路由;只有明确不提供IPv6服务时,才考虑撤销无效记录。

还要注意,FreeBSD中的 /etc/resolv.conf 主要影响服务器自身发起的DNS查询,例如应用连接数据库域名或外部接口。它通常不会决定访客如何解析网站域名,因此修改该文件不能解决权威DNS记录指向错误的问题。

核对DNS地址与服务器实际网络入口

登录 FreeBSD 服务器后,先查看接口地址和路由。以下命令以只读检查为主:

ifconfig -a
netstat -rn -f inet
route -n get default

如使用IPv6,还应查看IPv6路由:

netstat -rn -f inet6

判断时不能只比较 ifconfig 输出与DNS记录。如果服务器位于NAT、端口映射或前置网关之后,系统接口上看到的可能是私网地址,而DNS指向的是公网入口。此时还需要核对:

  • 公网地址是否仍映射到当前服务器。
  • TCP 80、443或业务端口是否完成转发。
  • 网关健康检查是否将该节点移出。
  • 是否存在旧服务器、旧NAT规则或错误的目标地址。
  • 返回流量是否经由正确网关出去。

ping 成功不能证明业务端口开放,ping 失败也不能证明服务器离线,因为ICMP可能被限制。端口访问应使用TCP连接测试。

从服务器外部执行:

nc -vz -w 5 example.com 80
nc -vz -w 5 example.com 443

结果可按以下方式理解:

  • 成功:TCP连接已建立,可以继续检查TLS、代理和应用。
  • refused:请求大概率已经到达目标主机,但端口没有监听,或防火墙主动拒绝。
  • 超时:可能是上游路由、NAT、防火墙丢弃、地址错误或返回路径异常,需要结合抓包判断。

端口监听状态比服务进程名称更有判断力

服务进程存在,不代表它监听了正确地址和端口。FreeBSD可使用 sockstat 查看监听套接字:

sockstat -4 -l
sockstat -6 -l

重点观察本地地址:

  • 127.0.0.1:8080:只能从本机IPv4访问。
  • 192.0.2.10:443:只监听指定IPv4地址。
  • *:80:通常表示监听所有IPv4地址。
  • ::1:8080:只允许本机IPv6访问。
  • IPv6通配监听是否同时接受IPv4,取决于系统和应用配置,不能直接假设。

如果业务本应直接向公网提供443端口,但 sockstat 中没有对应监听,应检查服务状态和启动日志,而不是先开放防火墙。

可先列出已启用的服务,再检查具体服务:

service -e
service nginx status

服务名取决于实际安装的软件,不能假设一定是 Nginx。若使用 Apache、HAProxy或自建应用,应替换为对应的 rc.d 服务名。

还可以分别测试回环地址和业务地址:

nc -vz 127.0.0.1 443
nc -vz 192.0.2.10 443

如果回环地址成功而业务地址失败,常见原因是服务只绑定了本地地址;如果两者都成功,但外部仍然超时,则应重点检查主机防火墙、上游入口和回程路由。

用抓包确认请求是否真正到达FreeBSD服务器

当外部测试超时时,tcpdump 是区分“流量没到服务器”和“服务器收到后未响应”的关键工具。

抓包可能包含客户端地址、域名或业务数据,应限制过滤条件和抓取数量,不要在生产环境长时间无过滤抓包。先通过 ifconfig 确认接口名称,再执行:

sudo tcpdump -ni em0 -c 50 'tcp port 80 or tcp port 443'

如果没有配置 sudo,应通过受控的 root 会话执行。将 em0 替换为实际外网接口。

在外部客户端重新发起一次访问,并观察结果:

  • 完全看不到入站SYN:DNS可能指向其他地址,或流量在上游路由、NAT、外部防火墙处被拦截。
  • 能看到SYN,但没有SYN-ACK或RST:主机防火墙可能丢弃数据包,也可能存在协议栈或返回路径问题。
  • 看到SYN后立即返回RST:通常是端口没有监听,或规则主动拒绝连接。
  • TCP三次握手完成:网络入口和TCP端口基本可用,应转向TLS、代理或应用层。
  • 服务器发出SYN-ACK,但客户端继续重传SYN:可能存在回程路由错误,或返回包在中间路径被丢弃。

抓包证据比“服务器能上网”更有价值。服务器能够访问外部网站,只能说明部分出站路径可用,不能证明公网入站和回程路径正常。

分清PF、IPFW与上游防火墙

FreeBSD环境可能使用PF、IPFW,也可能没有启用主机防火墙,而由上游网关控制访问。先确认实际使用哪一种,不要同时套用两套规则。

查看PF状态和规则:

sudo pfctl -s info
sudo pfctl -sr
sudo pfctl -sn
sudo pfctl -vvs rules

其中:

  • pfctl -sr 查看过滤规则。
  • pfctl -sn 查看NAT规则。
  • pfctl -vvs rules 可显示规则及累计计数器。

查看IPFW规则和计数器:

sudo ipfw list
sudo ipfw -a list

规则计数器应与一次受控复测结合使用。测试前后某条规则的计数增加,说明流量命中了它;计数没有变化,不能立即认定规则正确,还可能是流量没有到达、匹配了更前面的规则,或接口、地址族、协议条件不一致。

修改防火墙前先保留控制通道

远程修改防火墙可能中断SSH。操作前应确认有控制台、带外管理或其他恢复方式,并备份配置。以PF为例:

sudo cp -p /etc/pf.conf "/etc/pf.conf.bak.$(date +%Y%m%d%H%M%S)"
sudo pfctl -nf /etc/pf.conf

pfctl -nf 只做语法检查,不加载配置。修改完成后,应再次确认以下规则均存在:

  • 当前SSH管理来源和端口允许访问。
  • Web端口匹配正确的外网接口。
  • IPv4与IPv6规则符合实际DNS记录。
  • 返回流量和状态跟踪规则没有被破坏。
  • NAT场景中的目标地址与转换方向正确。

一个PF入站规则的概念示例如下:

ext_if="em0"
web_ports="{ 80, 443 }"

pass in on $ext_if inet proto tcp from any to ($ext_if) port $web_ports flags S/SA keep state

该示例仅展示IPv4 Web端口的匹配思路,不能直接替换现有 /etc/pf.conf。接口名称、多IP绑定、NAT、IPv6以及默认拒绝策略都可能要求不同写法。完成备份、语法检查并确认管理规则后,才可按维护流程加载:

sudo pfctl -f /etc/pf.conf

若加载后访问异常,应通过控制台使用备份文件恢复,而不是执行清空全部规则之类的高风险操作。

对于IPFW,也应先阅读现有规则顺序。IPFW按规则编号匹配,新增允许规则如果位于更早的拒绝规则之后,仍然不会生效。修复应写回实际使用的持久化配置或启动脚本,不能只依赖临时命令。

TCP端口正常后再检查代理和应用

如果外部TCP连接成功,但网页仍返回404、502、504或TLS错误,故障范围已经进入代理和应用层。

确认虚拟主机、Host与SNI

同一IP和端口可能承载多个站点。直接访问IP时,代理可能返回默认站点,因此应带上正确的域名测试。

如果安装了 curl,可在服务器本机测试HTTP虚拟主机:

curl -v http://127.0.0.1/ -H 'Host: example.com'

测试HTTPS站点及SNI:

curl -vk --resolve example.com:443:127.0.0.1 https://example.com/

结果判断:

  • 本机访问成功、外部失败:重点检查防火墙、NAT和网络入口。
  • 返回默认证书或错误站点:检查监听端口、SNI及虚拟主机匹配。
  • 返回404:请求已经到达HTTP服务,但域名、路径或路由配置可能不匹配。
  • TLS握手失败:检查证书文件、私钥权限、协议配置和系统时间。

检查反向代理与上游应用的关系

以Nginx为例,FreeBSD软件包的配置通常位于 /usr/local/etc/nginx/,但日志路径和包含文件由实际配置决定,应通过配置检查确认,而不是猜测固定路径。

sudo nginx -t
sudo nginx -T 2>&1 | grep -E 'listen|server_name|proxy_pass|access_log|error_log'

完整配置可能包含内部地址或敏感参数,不应直接复制到公开渠道。

如果代理配置为将请求转发到 127.0.0.1:8080,应确认上游确实监听:

sockstat -4 -l | grep ':8080'
nc -vz 127.0.0.1 8080

如应用提供健康检查接口,还可进行本机访问:

curl -v http://127.0.0.1:8080/health

需要结合应用实际路径,不能假设所有程序都有 /health。

代理访问日志和错误日志能够进一步区分问题:

  • 访问日志没有请求:请求可能未到代理,或命中了其他虚拟主机及日志文件。
  • connect() failed:上游端口未监听、地址错误或本机策略阻断。
  • upstream timed out:上游接受连接后未及时返回,需要检查应用日志和外部依赖。
  • 502伴随应用重启:可能是进程退出、启动失败或套接字短暂不可用。
  • 代理返回正常,但页面功能异常:继续检查应用路由、数据库连接和依赖服务,而不是调整公网端口。

按证据链解释结果,避免无依据重启

一次完整复测应同时保留外部现象、服务器监听、抓包、规则计数和应用日志。可以按以下顺序收敛范围:

  1. 域名没有返回预期地址:修复DNS记录或权威DNS配置,暂不调整服务器防火墙。
  2. 域名正确,但服务器抓不到SYN:检查上游入口、NAT、外部防火墙和路由。
  3. 服务器收到SYN并返回RST:检查端口监听、服务状态和绑定地址。
  4. 服务器收到SYN但不响应:检查PF、IPFW规则及回程路由。
  5. TCP握手成功但TLS失败:检查证书、SNI、时间和TLS监听配置。
  6. TLS成功但出现404:检查虚拟主机、Host和应用路由。
  7. 返回502或504:检查反向代理上游地址、应用端口、应用日志和依赖响应。
  8. 本机访问正常而外部失败:故障重点仍在公网入口、防火墙、NAT或地址族差异。

修改完成后,不要只在服务器本机执行一次访问。至少应从服务器外部重新验证A与AAAA记录、80与443端口、TLS证书、目标页面和关键接口,并同步观察 tcpdump、防火墙规则计数及代理日志。只有DNS结果正确、TCP握手完整、规则命中符合预期、应用返回正确状态码,这次修复才形成了可复现的证据闭环。

上一篇 从零搭建最小可用Neo4j服务器:基础配置、首次启动与连通性验证 下一篇 为日本独立服务器设置监控告警,哪些指标能识别故障前兆并减少误报

LHIDC 产品中心

继续查看可购买的海外服务器产品

文章用于辅助选型,最终价格、库存与配置请以产品详情页和下单页面展示为准。

查看产品 查看方案