【Linux】网络进阶:内网穿透、DNS与ICMP实战
本文介绍了内网穿透、DNS与ICMP三大网络实战技术。首先详细讲解内网穿透原理,通过frp工具实现SSH和Web服务穿透NAT的完整部署流程;其次解析DNS域名系统工作原理,演示dig工具的使用方法;最后剖析ICMP协议,说明ping和traceroute的网络诊断机制。文章包含大量实战内容,如frp配置教程、DNS查询过程解析,以及"浏览器输入URL后发生什么"的经典面试题解
网络进阶:内网穿透、DNS与ICMP实战
💬 开篇:上一篇我们学习了NAT技术和代理服务器,知道了NAT会阻止外网主动访问内网。那么问题来了:如何在没有公网IP的情况下,让外网访问家里的服务器?如何让浏览器知道域名对应的IP地址?如何诊断网络故障?这篇文章将详细讲解内网穿透技术(frp实战部署)、DNS域名解析系统(dig工具使用)、ICMP协议(ping和traceroute原理),帮助你掌握这些实用的网络技术。
👍 点赞、收藏与分享:这篇包含大量实战内容——frp完整部署教程、dig工具使用、网络诊断技巧,还有"浏览器输入URL后发生的事情"这道经典面试题的完整解答。如果对你有帮助,请点赞收藏!
🚀 循序渐进:从内网穿透的原理讲起,到frp实战部署(SSH、Web服务),到DNS解析过程,到ICMP协议应用,一步步掌握网络实战技能。
一、内网穿透
1.1 内网穿透的需求
1. 问题的由来
典型场景:
你在家里搭建了一个服务器:
* 运行了一个网站
* 或者运行了NAS(网络存储)
* 或者搭建了游戏服务器
但是:
* 家里的网络是通过NAT上网的
* 没有公网IP(或者是动态公网IP)
* 外网无法主动访问你的服务器
你想在公司、学校、咖啡厅访问家里的服务器
怎么办?
NAT带来的限制:
前面讲过,NAT的缺陷:
无法从外部主动建立连接
家里的服务器:192.168.1.100
路由器的公网IP:202.244.174.37
你的朋友想访问你的服务器:
1. 朋友访问 202.244.174.37:80
2. 路由器收到请求
3. 路由器查NAPT表:没有对应的表项(因为是外部主动连接)
4. 路由器不知道转发给谁
5. 丢弃请求
6. 访问失败
即使配置端口映射,仍有问题:
* 很多宽带没有公网IP
* 公网IP是动态的,会变化
* 配置复杂,不方便
2. 解决方案:内网穿透
内网穿透的原理:
通过一台有公网IP的服务器做中转
内网服务器主动连接公网服务器
外部用户访问公网服务器
公网服务器把流量转发给内网服务器
关键:内网到公网是主动连接,可以穿透NAT!
基本架构:
内网服务器 ←────────┐
(192.168.1.100) │ 主动连接
↓
公网服务器
(123.45.67.89)
↑
外网──────────→┘
1.2 内网穿透核心原理:反向连接与中继转发
1. 内网穿透的核心思想
问题:
外网 → 内网:被NAT阻止 ✗
内网 → 外网:可以穿透NAT ✓
解决思路:
让内网服务器主动建立连接
保持连接不断
外网的数据通过这个连接反向传输
类比:打电话
你在家里(内网)
朋友在公司(外网)
朋友想找你:
* 直接打你家座机:打不通(被拦截)✗
解决办法:
* 你主动打电话给朋友(内网主动连接)✓
* 保持通话不挂断
* 朋友有话要说,通过这个通话传递
2. 详细工作流程
角色说明:
* 内网客户端(frpc):部署在家里的电脑上
* 公网服务器(frps):部署在有公网IP的服务器上
* 外网用户:想要访问你家里服务的人
Step 1:建立控制连接
内网客户端启动后:
1动连接公网服务器的控制端口(如7000)
2. 发送配置信息:
* 我要暴露本地的22端口(SSH)
* 请在公网服务器上监听6000端口
3. 建立长连接,保持不断
4. 定期发送心跳包
公网服务器:
1. 收到内网客户端的连接
2. 在6000端口开始监听
3. 等待外网用户的访问
Step 2:外网用户发起访问
外网用户要SSH到你家里的电脑:
ssh user@123.45.67.89 -p 6000
↑ ↑
公网服务器的IP 公网服务器监听的端口
Step 3:公网服务器转发请求
公网服务器:
1. 收到6000端口的连接请求
2. 查找:这个端口对应哪个内网客户端?
3. 找到:对应家里的电脑
4. 通过控制连接通知内网客户端:"有新连接来了"
Step 4:建立数据连接
内网客户端:
1. 收到通知:"有新连接"
2. 再次主动连接公网服务器(建立数据连接)
3. 连接本地的SSH服务(127.0.0.1:22)
4. 开始转发数据
公网服务器:
1. 将外网用户的数据 → 转发到内网客户端
2. 将内网客户端的数据 → 转发到外网用户
完整流程图:
外网用户 公网服务器(frps) 内网客户端(frpc) 本地SSH服务
| | | |
| | ←──────────────── | 控制连接 |
| | (frpc主动连接) | (一直保持) |
| | | |
| SSH连接请求 | | |
| (6000端口) | | |
|─── 通知:"新连接" | |
| |───────────────────→| |
| | | 建立数据连接 |
| | ←──────────────── | (主动连接) |
| | | |
| | | 连接本地SSH |
| | |─────────────────→|
| | | |
| SSH数据 | | |
|───────────────→ |───────────────────→|─────────────────→|
| | | |
| | ←──────────────── | ←───────────────|
| ←───────────────| | |
| | | |
关键点:
1. 内网客户端始终主动连接公网服务器(穿透NAT)
2. 保持控制连接不断(用于通知)
3. 每个新访问建立新的数据连接(用于传输)
4. 公网服务器只是中转,不处理业务逻辑
1.3 frp实战部署
1. frp简介
frp(Fast Reverse Proxy):
一个开源的内网穿透工具
用Go语言开发
支持TCP、UDP、HTTP、HTTPS等协议
配置简单,性能优秀
项目地址:https://github.com/fatedier/frp
frp的组成:
frps(服务端):
* 部署在公网服务器上
* 接收内网客户端的连接
* 监听端口供外网访问
frpc(客户端):
* 部署在内网机器上
* 主动连接frps
* 转发流量到本地服务
2. 准备工作
所需资源:
1. 公网服务器一台:
* 有公网IP
* 操作系统:Linux(Ubuntu/CentOS等)
* 开放必要的端口
2. 内网机器(你家的电脑):
* 能访问互联网
* 运行需要暴露的服务(SSH、Nginx等)
3. frp软件:
* 下载地址:[https://github.com/fatedier/frp/releases](https://github.com/fatedier/frp/releases)
* 选择适合你操作系统的版本
下载frp:
# 在公网服务器和内网机器上都需要下载
# Linux x86_64
wget https://github.com/fatedier/frp/releases/download/v0.58.1/frp_0.58.1_linux_amd64.tar.gz
# 解压
tar -xzf frp_0.58.1_linux_amd64.tar.gz
cd frp_0.58.1_linux_amd64
frp的文件结构:
frp_0.58.1_linux_amd64/
├── frps # 服务端程序
├── frps.toml # 服务端配置文件
├── frpc # 客户端程序
├── frpc.toml # 客户端配置文件
└── LICENSE
3. 部署frps(公网服务器)
配置frps:
# 编辑服务端配置文件
vi frps.toml
frps.toml内容:
# frps.toml - 服务端配置
# bindPort = 7000
# 可选:Dashboard(管理面板)
# webServer.addr = "0.0.0.0"
# webServer.port = 7500
# webServer.user = "admin"
# webServer.password = "admin123"
启动frps:
# 前台运行(测试用)
./frps -c ./frps.toml
# 后台运行(生产环境)
nohup ./frps -c ./frps.toml &> frps.log &
# 查看进程
ps aux | grep frps
# 查看日志
tail -f frps.log
开放防火墙端口:
# Ubuntu/Debian
sudo ufw allow 7000/tcp # frps监听端口
sudo ufw allow 6000/tcp # 供外网访问的端口(SSH映射)
sudo ufw allow 8080/tcp # 供外网访问的端口(Nginx映射)
# CentOS/RHEL
sudo firewall-cmd --permanent --add-port=7000/tcp
sudo firewall-cmd --permanent --add-port=6000/tcp
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
4. 场景1:SSH远程登录
需求:
在公司远程SSH到家里的电脑
家里的电脑:运行SSH服务(22端口)
家里没有公网IP
配置frpc:
# 在家里的电脑上编辑客户端配置
vi frpc.toml
frpc.toml内容:
# frpc.toml - 客户端配置
# 公网服务器的地址和端口
serverAddr = "123.45.67.89" # 替换成你的公网服务器IP
serverPort = 7000
# 定义一个SSH服务的代理
[[proxies]]
name = "ssh" # 代理名称(任意)
type = "tcp" # 协议类型
localIP = "127.0.0.1" # 本地IP
localPort = 22 # 本地端口(SSH默认22)
remotePort = 6000 # 公网服务器监听的端口
启动frpc:
# 前台运行(测试用)
./frpc -c ./frpc.toml
# 后台运行
nohup ./frpc -c ./frpc.toml &> frpc.log &
# 查看日志
tail -f frpc.log
测试连接:
# 在公司的电脑上,SSH连接公网服务器的6000端口
ssh your_username@123.45.67.89 -p 6000
# 实际上会连接到家里电脑的22端口
# 成功!你现在可以远程操作家里的电脑了
工作流程:
公司电脑 → 公网服务器(123.45.67.89:6000)
→ frps转发
→ frpc接收
→ 家里电脑(127.0.0.1:22)
5. 场景2:远程访问Nginx网站
需求:
家里搭建了一个网站(Nginx)
想让朋友也能访问
安装Nginx(如果还没安装):
# Ubuntu/Debian
sudo apt install nginx
# CentOS/RHEL
sudo yum install nginx
# 启动Nginx
sudo systemctl start nginx
# 默认监听80端口
修改Nginx首页(可选):
# Ubuntu
sudo vi /var/www/html/index.nginx-debian.html
# CentOS
sudo vi /usr/share/nginx/html/index.html
# 改成自己的内容,比如:
# <h1>Welcome to My Home Server!</h1>
配置frpc(添加Nginx代理):
# frpc.toml
serverAddr = "123.45.67.89"
serverPort = 7000
# SSH服务(之前的配置保留)
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000
# Nginx服务(新增)
[[proxies]]
name = "web"
type = "tcp"
localIP = "127.0.0.1"
localPort = 80
remotePort = 8080
重启frpc:
# 停止之前的frpc
pkill frpc
# 重新启动
nohup ./frpc -c ./frpc.toml &> frpc.log &
测试访问:
# 在浏览器中访问:
http://123.45.67.89:8080
# 或者用curl:
curl http://123.45.67.89:8080
# 应该能看到你家里Nginx的页面
6. 高级配置:HTTP代理
HTTP代理的好处:
使用TCP代理需要指定端口(如8080)
使用HTTP代理可以通过域名访问(更友好)
前提条件:
你有一个域名(如:home.example.com)
域名解析到公网服务器的IP
修改frps配置:
# frps.toml
bindPort = 7000
# 添加HTTP支持
vhostHTTPPort = 80 # HTTP虚拟主机端口
修改frpc配置:
# frpc.toml
serverAddr = "123.45.67.89"
serverPort = 7000
# Nginx服务(使用HTTP类型)
[[proxies]]
name = "web"
type = "http" # 改成HTTP类型
localIP = "127.0.0.1"
localPort = 80
customDomains = ["home.example.com"] # 绑定域名
重启frps和frpc:
# 公网服务器
pkill frps
nohup ./frps -c ./frps.toml &> frps.log &
# 家里的电脑
pkill frpc
nohup ./frpc -c ./frpc.toml &> frpc.log &
访问测试:
# 直接通过域名访问(不需要端口号)
http://home.example.com
# 更加友好!
7. 安全建议
1. 加密传输:
# frps.toml
transport.tls.enable = true
# frpc.toml
transport.tls.enable = true
2. 身份验证:
# frps.toml
auth.method = "token"
auth.token = "your_secret_token_12345"
# frpc.toml
auth.method = "token"
auth.token = "your_secret_token_12345"
3. 限制访问:
# 在公网服务器上配置防火墙
# 只允许特定IP访问
sudo ufw allow from 1.2.3.4 to any port 6000
4. 使用HTTPS:
# frpc.toml
[[proxies]]
name = "web-https"
type = "https"
localIP = "127.0.0.1"
localPort = 443
customDomains = ["home.example.com"]
8. 常见问题
1. 连接失败:
检查清单:
□ 公网服务器的frps是否正常运行
□ 防火墙端口是否开放
□ frpc配置的serverAddr和serverPort是否正确
□ 本地服务是否正常运行
2. 连接不稳定:
可能原因:
- 网络不稳定
- frpc进程被kill
- 超时断开
解决方案:
- 配置心跳检测
- 配置自动重启
- 使用systemd管理frpc
3. 性能问题:
所有流量都通过公网服务器中转
会有性能损耗
改进方案:
- 选择带宽充足的公网服务器
- 使用P2P模式(需要两端都支持)
- 考虑使用专业的内网穿透服务
4. 使用systemd管理frpc(推荐):
# 创建systemd服务文件
sudo vi /etc/systemd/system/frpc.service
# 内容:
[Unit]
Description=FRP Client
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/path/to/frp
ExecStart=/path/to/frp/frpc -c /path/to/frp/frpc.toml
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
# 启动服务
sudo systemctl start frpc
sudo systemctl enable frpc # 开机自启
# 查看状态
sudo systemctl status frpc
二、DNS域名解析系统
2.1 DNS的背景
1. IP地址不方便记忆
问题:
TCP/IP网络使用IP地址和端口号定位主机和服务
但IP地址是数字,不方便记忆
例如:
- 百度:180.101.49.11
- 谷歌:142.250.185.46
- GitHub:20.205.243.166
试想:如果没有域名,你能记住这些IP吗?
早期的解决方案:hosts文件:
人们发明了"主机名"(hostname)
使用hosts文件描述主机名和IP的对应关系
hosts文件内容示例:
180.101.49.11 www.baidu.com
142.250.185.46 www.google.com
20.205.243.166 github.com
访问网站时:
1. 用户输入:www.baidu.com
2. 系统查hosts文件
3. 找到对应IP:180.101.49.11
4. 连接这个IP
hosts文件的问题:
最初,hosts文件由互联网信息中心(SRI-NIC)集中管理
遇到的困难:
1. 新电脑接入网络,需要向信息中心申请添加记录
2. IP变更,需要向信息中心申请修改
3. 其他电脑需要定期下载更新hosts文件
4. 互联网规模增长,hosts文件变得巨大
5. 管理和同步极其困难
无法扩展!
2. DNS系统的诞生
DNS的设计思想:
分布式管理:
- 不再集中管理一个文件
- 每个组织管理自己的域名
- 通过DNS服务器提供查询
自动查询:
- 用户输入域名
- 系统自动查询DNS服务器
- 获得对应的IP地址
- 无需手动维护hosts文件
DNS的好处:
✓ 可扩展:每个组织管理自己的域名
✓ 自动化:系统自动查询,无需手动更新
✓ 灵活:IP变更只需更新DNS服务器
✓ 高效:DNS服务器缓存查询结果
hosts文件的保留:
至今,计算机上仍保留hosts文件
在DNS查询之前,会先查hosts文件
位置:
- Linux/Mac: /etc/hosts
- Windows: C:\Windows\System32\drivers\etc\hosts
优先级:
hosts文件 > DNS查询
用途:
- 本地开发(配置测试域名)
- 屏蔽广告(把广告域名指向127.0.0.1)
- 绕过DNS污染
2.2 域名的结构
1. 域名的层次结构
域名是树状结构:
.(根)
|
┌───────────────┼───────────────┐
| | |
com net org cn
| | | |
┌───┴───┐ ┌───┴───┐ ┌───┴───┐ ┌───┴───┐
baidu google cloudflare github wikipedia baidu qq
| | | | | | |
www www www www www www www

从右到左阅读:
www.baidu.com
│ │ └─ 一级域名(顶级域名,TLD)
│ └────── 二级域名
└─────────── 三级域名(主机名)
完整域名(FQDN):
www.baidu.com.
↑
根域名(通常省略)
完整的域名应该以点结尾
但我们平时都省略了
2. 各级域名详解
根域名(Root):
符号:.
全球只有13组根DNS服务器
负责管理顶级域名
一级域名(顶级域名,TLD):
通用顶级域名(gTLD):
- .com:商业机构
- .net:网络服务提供商
- .org:非盈利组织
- .edu:教育机构
- .gov:政府机构
- .mil:军事机构
- .int:国际组织
国家/地区顶级域名(ccTLD):
- .cn:中国
- .us:美国
- .uk:英国
- .jp:日本
- .de:德国
新通用顶级域名:
- .tech:技术
- .app:应用
- .blog:博客
- .shop:商店
二级域名:
通常是企业名、组织名、个人名
由域名注册商注册获得
例子:
- baidu.com:百度公司
- google.com:谷歌公司
- github.com:GitHub平台
在某些国家,还有特定的二级域名:
- .com.cn:中国的商业域名
- .gov.cn:中国的政府域名
- .edu.cn:中国的教育域名
三级及以上域名(子域名):
由二级域名的所有者自行创建和管理
例子:
www.baidu.com:
- www:三级域名,通常表示万维网服务
mail.google.com:
- mail:三级域名,谷歌的邮箱服务
api.github.com:
- api:三级域名,GitHub的API服务
blog.csdn.net:
- blog:三级域名,CSDN的博客服务
3. www的由来
www不是必需的:
www是一种习惯用法
历史上,人们常用子域名表示服务类型:
www.example.com → 网站服务(World Wide Web)
ftp.example.com → FTP文件传输服务
mail.example.com → 邮件服务
现代趋势:
很多网站不再使用www:
- google.com(不需要www)
- facebook.com
- twitter.com
但也有网站保留www:
- www.baidu.com
- www.qq.com
- www.taobao.com
技术上,example.com和www.example.com可以:
- 指向同一个IP(完全相同)
- 指向不同的IP(不同服务)
- 一个重定向到另一个
2.3 DNS解析过程
1. DNS查询的类型
递归查询:
客户端向DNS服务器发起查询
DNS服务器负责完成整个查询过程
返回最终结果给客户端
客户端 → DNS服务器:"帮我查www.baidu.com"
DNS服务器:自己去查,查到后返回结果
客户端 ← DNS服务器:"IP是180.101.49.11"
迭代查询:
DNS服务器之间的查询
如果自己不知道,返回下一个应该查询的服务器地址
DNS服务器A → 根服务器:"www.baidu.com是多少?"
根服务器 → DNS服务器A:"我不知道,但你可以问.com服务器"
DNS服务器A → .com服务器:"www.baidu.com是多少?"
.com服务器 → DNS服务器A:"我不知道,但你可以问baidu.com服务器"
...
2. 完整的DNS解析流程
场景:你在浏览器输入 www.baidu.com
Step 1:检查浏览器缓存
浏览器自己缓存了DNS解析结果
如果之前访问过www.baidu.com,可能有缓存
检查缓存,如果有且未过期,直接使用
Step 2:检查系统缓存
操作系统也有DNS缓存
Windows:ipconfig /displaydns 可以查看
Linux:Linux 是否有系统级缓存取决于发行版/组件(如 systemd-resolved、dnsmasq、nscd 等)。
Step 3:检查hosts文件
查看/etc/hosts(Linux)或C:\Windows\System32\drivers\etc\hosts(Windows)
如果hosts文件中有www.baidu.com的记录,直接使用
Step 4:向本地DNS服务器查询(递归查询)
本地DNS服务器:
- 通常是ISP(运营商)提供的DNS服务器
- 或者是手动配置的DNS服务器(如8.8.8.8,114.114.114.114)
客户端 → 本地DNS服务器(如192.168.1.1)
请求:查询www.baidu.com
本地DNS服务器先检查自己的缓存
如果有缓存且未过期,直接返回
Step 5:本地DNS服务器向根服务器查询(迭代查询)
本地DNS服务器 → 根DNS服务器
请求:"www.baidu.com的IP是多少?"
根DNS服务器 → 本地DNS服务器
响应:"我不知道www.baidu.com,但我知道.com域由哪些服务器管理"
"去问这些.com顶级域名服务器:[.com NS列表]"
Step 6:向顶级域名服务器查询
本地DNS服务器 → .com顶级域名服务器
请求:"www.baidu.com的IP是多少?"
.com服务器 → 本地DNS服务器
响应:"我不知道www.baidu.com,但我知道baidu.com域由哪些服务器管理"
"去问这些baidu.com权威DNS服务器:[baidu.com NS列表]"
Step 7:向权威DNS服务器查询
本地DNS服务器 → baidu.com权威DNS服务器
请求:"www.baidu.com的IP是多少?"
baidu.com服务器 → 本地DNS服务器
响应:"www.baidu.com的IP是180.101.49.11"
"TTL=600秒"
Step 8:本地DNS服务器缓存并返回
本地DNS服务器:
1. 缓存这个解析结果(600秒)
2. 返回给客户端
本地DNS服务器 → 客户端
响应:"www.baidu.com的IP是180.101.49.11"
Step 9:客户端连接
客户端获得IP地址:180.101.49.11
建立TCP连接
发送HTTP请求
完整流程图:
客户端 本地DNS 根DNS .com DNS baidu.com DNS
| | | | |
| 1.查询 | | | |
| www.baidu.com | | | |
|-------------------->| | | |
| | 2.查询 | | |
| |---------->| | |
| | 3.返回 | | |
| | .com NS | | |
| |<----------| | |
| | | |
| | 4.查询 | |
| |-------------------->| |
| | 5.返回 | |
| | baidu.com NS | |
| |<--------------------| |
| | |
| | 6.查询 |
| |--------------------------------->|
| | 7.返回IP: 180.101.49.11 |
| |<---------------------------------|
| | |
| 8.返回IP | |
|<--------------------| |
| |
| 9.连接180.101.49.11 |
|-------------------------------------------------------->百度服务器

2.4 使用dig工具分析DNS
1. 安装dig工具
# CentOS/RHEL
sudo yum install bind-utils
# Ubuntu/Debian
sudo apt install dnsutils
# macOS
# dig通常已预装
2. 基本用法
查询域名:
dig www.baidu.com
# 输出示例:
; <<>> DiG 9.16.1-Ubuntu <<>> www.baidu.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12345
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; QUESTION SECTION:
;www.baidu.com. IN A
;; ANSWER SECTION:
www.baidu.com. 600 IN CNAME www.a.shifen.com.
www.a.shifen.com. 300 IN A 180.101.49.11
www.a.shifen.com. 300 IN A 180.101.49.12
;; Query time: 10 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Mon Jan 15 10:00:00 CST 2024
;; MSG SIZE rcvd: 100
输出解释:
1. 开头部分:
dig版本信息和查询的域名
2. HEADER部分:
status: NOERROR → 查询成功
flags: qr rd ra → 查询标志
qr: 这是一个响应(query response)
rd: 期望递归查询(recursion desired)
ra: 服务器支持递归(recursion available)
QUERY: 1 → 1个查询
ANSWER: 3 → 3个答案记录
3. QUESTION SECTION:
查询的问题:
www.baidu.com. IN A
│ └ A记录(IPv4地址)
└ IN表示Internet类
4. ANSWER SECTION:
查询结果:
www.baidu.com. 600 IN CNAME www.a.shifen.com.
│ └ CNAME:别名记录
└ TTL=600秒(10分钟)
www.a.shifen.com. 300 IN A 180.101.49.11
│ └ IP地址
└ TTL=300秒(5分钟)
解释:
- www.baidu.com 是 www.a.shifen.com 的别名
- www.a.shifen.com 解析到两个IP地址(负载均衡)
5. 统计信息:
Query time: 10 msec → 查询耗时10毫秒
SERVER: 192.168.1.1#53 → 使用的DNS服务器及端口
3. 常用选项
只显示答案:
dig +short www.baidu.com
# 输出:
www.a.shifen.com.
180.101.49.11
180.101.49.12
指定DNS服务器:
# 使用Google DNS
dig @8.8.8.8 www.baidu.com
# 使用114 DNS
dig @114.114.114.114 www.baidu.com
查询特定记录类型:
# 查询A记录(IPv4)
dig www.baidu.com A
# 查询AAAA记录(IPv6)
dig www.baidu.com AAAA
# 查询MX记录(邮件服务器)
dig baidu.com MX
# 查询NS记录(域名服务器)
dig baidu.com NS
# 查询TXT记录(文本记录,常用于验证)
dig baidu.com TXT
追踪完整解析过程:
dig +trace www.baidu.com
# 会显示从根服务器开始的完整查询过程
2.5 DNS缓存与TTL
1. 为什么需要缓存
性能优化:
DNS查询需要多次网络请求
每次都查询会很慢
有了缓存:
- 第一次查询:完整的DNS解析流程
- 后续查询:直接从缓存获取
- 大大提高速度
减少DNS服务器负载:
如果没有缓存:
- 每次访问网站都要查询DNS
- 全球数十亿设备,数千亿次查询
- DNS服务器压力巨大
有了缓存:
- 大量查询由本地缓存满足
- DNS服务器压力大幅降低
2. 多级缓存
浏览器缓存:
Chrome浏览器:
- 查看DNS缓存:chrome://net-internals/#dns
- 清除DNS缓存:chrome://net-internals/#dns → Clear host cache
操作系统缓存:
Windows:
- 查看:ipconfig /displaydns
- 清除:ipconfig /flushdns
Linux:
- 通常没有系统级缓存
- 如果安装了nscd:sudo systemctl restart nscd
macOS:
- 清除:sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
本地DNS服务器缓存:
ISP的DNS服务器缓存大量解析结果
TTL到期后才重新查询
3. TTL(生存时间)
TTL的作用:
控制缓存的有效期
例如:
www.baidu.com 600 IN A 180.101.49.11
│
TTL=600秒
意思:
- 这条记录可以缓存600秒(10分钟)
- 600秒后,需要重新查询
TTL的权衡:
TTL长(如86400秒=1天):
✓ 减少DNS查询
✓ 提高性能
✗ IP变更后生效慢
TTL短(如60秒):
✓ IP变更后快速生效
✗ 频繁查询DNS
✗ 性能略差
通常设置:
- 稳定的服务:TTL=3600秒(1小时)或更长
- 即将变更IP:提前降低TTL(如60秒)
- 变更完成后:再提高TTL
2.6 浏览器输入URL后发生的事情
经典面试题,综合考察网络知识
完整流程(以访问 http://www.baidu.com 为例):
1. URL解析:
浏览器解析URL:
协议:http
域名:www.baidu.com
端口:80(默认)
路径:/(根路径)
2. DNS解析:
浏览器发起DNS查询(前面详细讲过的9步流程)
获得IP地址:180.101.49.11
3. 建立TCP连接:
三次握手:
浏览器 → 服务器:SYN
浏览器 ← 服务器:SYN+ACK
浏览器 → 服务器:ACK
连接建立
4. 发送HTTP请求:
浏览器发送HTTP请求:
GET / HTTP/1.1
Host: www.baidu.com
User-Agent: Mozilla/5.0 ...
Accept: text/html...
...
5. 服务器处理请求:
服务器接收请求
解析请求
处理业务逻辑
生成响应
6. 服务器返回HTTP响应:
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 12345
...
<!DOCTYPE html>
<html>
...
</html>
7. 浏览器接收响应:
接收HTML内容
解析HTML
发现需要加载的资源(CSS、JS、图片)
8. 加载页面资源:
对于每个资源(CSS、JS、图片):
- 可能需要DNS解析(如果是不同域名)
- 建立TCP连接(或复用已有连接)
- 发送HTTP请求
- 接收响应
- 浏览器缓存资源
9. 渲染页面:
解析HTML → 构建DOM树
解析CSS → 构建CSSOM树
合并DOM和CSSOM → 渲染树
布局(Layout)
绘制(Paint)
合成(Composite)
页面显示
10. 执行JavaScript:
解析和执行JS代码
可能修改DOM
可能发起新的网络请求(Ajax)
11. 持续交互:
用户点击、滚动、输入
JavaScript处理事件
可能发起新的网络请求
更新页面内容
涉及的网络协议栈:
应用层:HTTP/HTTPS、DNS
传输层:TCP
网络层:IP、ICMP
数据链路层:以太网、ARP
物理层:网线、光纤、WiFi
三、ICMP协议
3.1 ICMP的作用
1. IP协议的局限性
IP协议是不可靠的:
IP协议负责数据包的传输
但不保证数据包一定能到达目的地
可能的问题:
- 数据包丢失
- 路由不可达
- TTL超时
- 目标主机不存在
IP协议本身不提供错误报告机制
需要一个辅助协议:
需要一个协议来:
1. 报告错误情况
2. 诊断网络问题
3. 测试网络连通性
ICMP就是这个协议!
2. ICMP协议简介
ICMP(Internet Control Message Protocol,互联网控制消息协议):
是网络层协议(虽然它封装在IP数据包中)
用于在IP主机和路由器之间传递控制消息
不传输数据,只传输控制信息
ICMP的主要功能:
1. 错误报告:
- 目标不可达
- 超时
- 参数错误
2. 网络诊断:
- Ping(测试连通性)
- Traceroute(跟踪路由)
ICMP与IP的关系:
ICMP虽然工作在网络层
但它仍然需要IP协议来传输ICMP消息
ICMP消息封装在IP数据包中:
┌────────────────────────────┐
│ IP首部 │
│ 协议号:1(ICMP) │
├────────────────────────────┤
│ ICMP消息 │
│ │
└────────────────────────────┘
3.2 ICMP报文格式
基本格式:
┌────────────────────────────────────────┐
│ 类型(Type)- 8位 │
├────────────────────────────────────────┤
│ 代码(Code)- 8位 │
├────────────────────────────────────────┤
│ 校验和(Checksum)- 16位 │
├────────────────────────────────────────┤
│ 数据部分(根据类型和代码变化) │
│ │
└────────────────────────────────────────┘
常见的ICMP消息类型:
| 类型 | 代码 | 说明 |
|---|---|---|
| 0 | 0 | Echo Reply(回显应答,Pong) |
| 3 | 0 | Destination Network Unreachable(目标网络不可达) |
| 3 | 1 | Destination Host Unreachable(目标主机不可达) |
| 3 | 2 | Destination Protocol Unreachable(目标协议不可达) |
| 3 | 3 | Destination Port Unreachable(目标端口不可达) |
| 5 | 0 | Redirect(重定向) |
| 8 | 0 | Echo Request(回显请求,Ping) |
| 11 | 0 | TTL Exceeded(TTL超时) |
| 11 | 1 | Fragment Reassembly Time Exceeded(分片重组超时) |
ICMP分为两大类:
1. 错误报告消息:
类型3:目标不可达
类型11:TTL超时
类型12:参数错误
...
2. 查询消息:
类型8:Echo Request(Ping请求)
类型0:Echo Reply(Ping应答)
类型13:时间戳请求
类型14:时间戳应答
...
3.3 ping命令
1. ping命令的作用
ping命令:
用于测试网络连通性
基于ICMP Echo Request/Reply实现
最常用的网络诊断工具
基本用法:
# ping域名
ping www.baidu.com
# ping IP地址
ping 180.101.49.11
# ping指定次数(Linux)
ping -c 4 www.baidu.com
# ping指定次数(Windows)
ping -n 4 www.baidu.com
# 持续ping(Linux默认,Windows用 -t)
ping www.baidu.com
2. ping命令的输出
示例输出:
$ ping www.baidu.com
PING www.a.shifen.com (180.101.49.11): 56 data bytes
64 bytes from 180.101.49.11: icmp_seq=0 ttl=52 time=10.2 ms
64 bytes from 180.101.49.11: icmp_seq=1 ttl=52 time=10.5 ms
64 bytes from 180.101.49.11: icmp_seq=2 ttl=52 time=10.3 ms
64 bytes from 180.101.49.11: icmp_seq=3 ttl=52 time=10.4 ms
--- www.a.shifen.com ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 10.2/10.4/10.5/0.1 ms
输出解释:
第一行:
PING www.a.shifen.com (180.101.49.11): 56 data bytes
│
└ DNS解析后的IP地址
每一行响应:
64 bytes from 180.101.49.11: icmp_seq=0 ttl=52 time=10.2 ms
│ │ │ │ │
│ │ │ │ └ 往返时间(RTT)
│ │ │ └ TTL值
│ │ └ 序列号
│ └ 响应来源IP
└ 数据包大小
统计信息:
4 packets transmitted → 发送了4个包
4 packets received → 收到了4个包
0.0% packet loss → 丢包率0%
round-trip min/avg/max/stddev = 10.2/10.4/10.5/0.1 ms
│ │ │ │
│ │ │ └ 标准差
│ │ └ 最大RTT
│ └ 平均RTT
└ 最小RTT
3. ping命令的工作原理
发送Echo Request:
1. ping程序构造ICMP Echo Request消息:
┌─────────────────────────────┐
│ 类型:8(Echo Request) │
│ 代码:0 │
│ 校验和:... │
│ 标识符:进程ID │
│ 序列号:递增(0, 1, 2...) │
│ 数据:填充数据 │
└─────────────────────────────┘
2. 封装在IP数据包中:
┌─────────────────────────────┐
│ IP首部 │
│ 源IP:你的IP │
│ 目的IP:180.101.49.11 │
│ 协议:1(ICMP) │
├─────────────────────────────┤
│ ICMP Echo Request │
└─────────────────────────────┘
3. 通过网络发送
4. 记录发送时间:t1
接收Echo Reply:
1. 目标主机收到Echo Request
2. 目标主机构造Echo Reply:
┌─────────────────────────────┐
│ 类型:0(Echo Reply) │
│ 代码:0 │
│ 校验和:... │
│ 标识符:与请求相同 │
│ 序列号:与请求相同 │
│ 数据:与请求相同 │
└─────────────────────────────┘
3. 返回给源主机
4. 源主机收到Echo Reply
5. 记录接收时间:t2
6. 计算RTT = t2 - t1
TTL的含义:
TTL(Time To Live,生存时间):
- IP数据包的跳数限制
- 每经过一个路由器,TTL减1
- TTL减到0时,路由器丢弃数据包,发送ICMP超时消息
ping显示的TTL:
- 是响应包返回时的TTL值
- 不是原始TTL值
例如:
- 百度服务器发送时:TTL=64
- 经过12跳路由器:TTL=64-12=52
- ping显示:ttl=52
通过TTL可以估算跳数:
- Linux/Mac默认TTL=64
- Windows默认TTL=128
- 跳数 ≈ 初始TTL - 当前TTL
4. ping的常见结果
成功:
64 bytes from 180.101.49.11: icmp_seq=0 ttl=52 time=10.2 ms
说明:
- 网络连通
- 目标主机可达
- 往返时间正常
目标主机不可达:
From 192.168.1.1 icmp_seq=1 Destination Host Unreachable
可能原因:
- 目标主机不存在
- 目标主机关机
- 路由不可达
- 防火墙阻止
请求超时:
Request timeout for icmp_seq 0
可能原因:
- 数据包丢失
- 目标主机关机或禁ping
- 网络拥塞
- 防火墙阻止ICMP
丢包:
64 bytes from 180.101.49.11: icmp_seq=0 ttl=52 time=10.2 ms
Request timeout for icmp_seq 1
64 bytes from 180.101.49.11: icmp_seq=2 ttl=52 time=10.5 ms
--- ping statistics ---
3 packets transmitted, 2 packets received, 33.3% packet loss
说明:
- 网络不稳定
- 有丢包
3.4 traceroute命令
1. traceroute的作用
traceroute命令:
跟踪数据包到达目标的路径
显示经过的每一个路由器
基于ICMP和TTL机制实现
基本用法:
# Linux/Mac
traceroute www.baidu.com
# Windows(命令名不同)
tracert www.baidu.com
2. traceroute的输出
示例输出:
$ traceroute www.baidu.com
traceroute to www.a.shifen.com (180.101.49.11), 30 hops max, 60 byte packets
1 192.168.1.1 (192.168.1.1) 1.234 ms 1.123 ms 1.156 ms
2 100.64.0.1 (100.64.0.1) 5.678 ms 5.234 ms 5.456 ms
3 61.148.10.1 (61.148.10.1) 8.234 ms 8.123 ms 8.345 ms
4 202.97.33.1 (202.97.33.1) 10.234 ms 10.123 ms 10.456 ms
5 202.97.50.1 (202.97.50.1) 12.234 ms 12.123 ms 12.345 ms
6 * * *
7 180.101.49.11 (180.101.49.11) 15.234 ms 15.123 ms 15.456 ms
输出解释:
第一行:
traceroute to www.a.shifen.com (180.101.49.11), 30 hops max, 60 byte packets
│ │
│ └ 数据包大小
└ 最大跳数
每一跳:
1 192.168.1.1 (192.168.1.1) 1.234 ms 1.123 ms 1.156 ms
│ │ │ │ │
│ │ │ │ └ 第3次测试的RTT
│ │ │ └ 第2次测试的RTT
│ │ └ 第1次测试的RTT
│ └ 路由器IP
└ 跳数
特殊符号:
*:表示超时,没有收到响应
可能原因:
- 路由器不响应ICMP
- 防火墙阻止
- 该跳丢包
3. traceroute的工作原理
基于TTL机制:
Step 1:发送TTL=1的数据包
1. traceroute发送UDP或ICMP数据包,TTL=1
2. 第一跳路由器收到:
- TTL减1,变成0
- 丢弃数据包
- 发送ICMP超时消息给源主机
3. 源主机收到ICMP超时消息:
- 获得第一跳路由器的IP
- 记录RTT
第一跳路由器:192.168.1.1
Step 2:发送TTL=2的数据包
1. traceroute发送数据包,TTL=2
2. 第一跳路由器:
- TTL减1,变成1
- 转发数据包
3. 第二跳路由器收到:
- TTL减1,变成0
- 丢弃数据包
- 发送ICMP超时消息
4. 源主机收到消息:
- 获得第二跳路由器的IP
- 记录RTT
第二跳路由器:100.64.0.1
Step 3:发送TTL=3的数据包
类似的过程...
第三跳路由器:61.148.10.1
持续增加TTL,直到:
1. 到达目标主机:
- 目标主机返回ICMP端口不可达(UDP方式)
- 或返回ICMP Echo Reply(ICMP方式)
2. 达到最大跳数(默认30)
结束
完整流程图:
源主机 路由器1 路由器2 目标主机
| | | |
| TTL=1 | | |
|------------------>| | |
| | TTL超时 | |
|<------------------| | |
| (ICMP超时消息) | | |
| | | |
| TTL=2 | | |
|------------------>| TTL=1 | |
| |--------------->| |
| | | TTL超时 |
| |<---------------| |
|<------------------| | |
| (ICMP超时消息) | | |
| | | |
| TTL=3 | | |
|------------------>| TTL=2 | |
| |--------------->| TTL=1 |
| | |--------------->|
| | | | 到达目标
| | |<---------------|
| |<---------------| |
|<------------------| | |
| (目标可达响应) | | |
3.5 重要提醒:ping不是端口!
常见的面试陷阱
错误的问题:
面试官:"telnet是23端口,ssh是22端口,那么ping是什么端口?"
正确的回答:
千万注意!这是面试官的圈套!
ping命令基于ICMP协议
ICMP是网络层协议
而端口号是传输层(TCP/UDP)的概念
在ICMP中根本就不关注端口号这样的信息
ping没有端口号!
为什么容易被误导:
因为很多网络工具都有对应的端口:
- telnet: 23端口(TCP)
- ssh: 22端口(TCP)
- http: 80端口(TCP)
- https: 443端口(TCP)
- DNS: 53端口(UDP/TCP)
所以很自然地认为ping也有端口
但是:
ping使用ICMP,不使用TCP/UDP
ICMP在网络层,比传输层更底层
没有端口的概念
ICMP报文的标识:
ICMP不使用端口号
而是使用类型(Type)和代码(Code)来区分不同的消息
ping使用:
- Echo Request:类型=8,代码=0
- Echo Reply:类型=0,代码=0
协议层次对比:
┌─────────────────────────────┐
│ 应用层(HTTP、FTP等) │
│ 使用URL、域名 │
├─────────────────────────────┤
│ 传输层(TCP、UDP) │
│ 使用端口号 │ ← telnet、ssh、http在这一层
├─────────────────────────────┤
│ 网络层(IP、ICMP) │
│ 使用IP地址 │ ← ping在这一层,没有端口!
├─────────────────────────────┤
│ 数据链路层(以太网) │
│ 使用MAC地址 │
├─────────────────────────────┤
│ 物理层 │
└─────────────────────────────┘
总结:
如果面试官问"ping是什么端口"
正确回ICMP是网络层协议。
端口号是传输层(TCP/UDP)的概念。
ICMP工作在网络层,不涉及端口号。
ICMP使用类型和代码字段来区分不同的消息,
ping使用的是Echo Request(类型8)和Echo Reply(类型0)。"
这样的回答能展示你对网络协议栈的深刻理解!
四、本篇总结
4.1 核心要点回顾
内网穿透:
- ✓ 通过公网服务器中转,解决NAT阻止外部主动连接的问题
- ✓ 内网客户端主动连接公网服务器,保持长连接
- ✓ frp实战:可以远程SSH、访问家里的网站、配置HTTP代理
- ✓ 安全建议:加密传输、身份验证、限制访问、使用HTTPS
DNS域名解析:
- ✓ DNS将域名转换为IP地址,采用分布式、层次化的设计
- ✓ 域名结构:根域名 → 顶级域名(.com) → 二级域名(baidu) → 三级域名(www)
- ✓ DNS解析过程:浏览器缓存 → 系统缓存 → hosts文件 → 递归查询 → 迭代查询(9步流程)
- ✓ dig工具实战:查询域名、指定DNS服务器、查询特定记录类型、追踪完整解析过程
- ✓ 多级DNS缓存和TTL机制提高性能
- ✓ 浏览器输入URL后发生的事情:URL解析 → DNS解析 → TCP连接 → HTTP请求/响应 → 渲染页面
ICMP协议:
- ✓ ICMP用于网络诊断和错误报告,是IP协议的辅助协议
- ✓ ping命令:测试网络连通性,基于ICMP Echo Request/Reply,显示RTT和TTL
- ✓ traceroute命令:跟踪数据包路径,基于TTL机制,显示每一跳路由器
- ✓ 重要:ping基于ICMP(网络层),没有端口号的概念!
4.2 常见面试题
1. 内网穿透的原理是什么?
答:
- 核心思想:内网客户端主动连接公网服务器(可以穿透NAT)
- 保持长连接不断
- 外网访问时,通过这个连接反 关键技术:控制连接(通知)、数据连接(传输)、中转服务器
2. 为什么需要DNS?hosts文件不够用吗?
答:
- hosts文件问题:集中管理无法扩展、手动同步效率低、文件巨大、IP变更需所有人更新
- DNS优势:分布式管理可扩展、自动查询无需手动维护、缓存机制提高效率、IP变更只需更新DNS服务器
3. DNS解析的完整过程是什么?
答:
1. 检查浏览器缓存
2. 检查系统缓存
3. 检查hosts文件
4. 向本地DNS服务器查询(递归查询)
5-7. 本地DNS服务器向根服务器、顶级域名服务器、权威DNS服务器查询(迭代查询)
8. 本地DNS服务器缓存并返回
9. 客户端连接
4. ping命令的工作原理?
答:
1. 发送ICMP Echo Request(类型8)
2. 目标主机收到后,返回ICMP Echo Reply(类型0)
3. 计算往返时间(RTT)
4. 根据TTL值估算跳数
关键点:
- 基于ICMP协议(网络层)
- 没有端口号的概念
- 可以测试连通性和延迟
5. traceroute是如何工作的?
答:
- 利用TTL机制
- 发送TTL=1的数据包,第一跳路由器超时,返回ICMP超时消息
- 发送TTL=2的数据包,第二跳路由器超时,返回ICMP超时消息
- 依次增加TTL,直到到达目标
- 每个路由器超时时返回自己的IP
- traceroute收集这些IP,显示路径
6. 浏览器输入URL后发生的事情?
答:
1. URL解析
2. DNS解析(获取IP地址)
3. 建立TCP连接(三次握手)
4. 发送HTTP请求
5. 服务器处理请求并返回响应
6. 浏览器接收响应,解析HTML
7. 加载页面资源(CSS、JS、图片)
8. 渲染页面(构建DOM树、CSSOM树、渲染树、布局、绘制)
9. 执行JavaScript
10. 持续交互
涉及协议:HTTP/HTTPS、DNS、TCP、IP、ICMP、以太网、ARP
如果是 HTTPS:TCP 三次握手之后还会有 TLS 1.2/1.3 握手,再发 HTTP(加密后)
7. 为什么ping不是端口?
答:
- ping基于ICMP协议,ICMP是网络层协议
- 端口号是传输层(TCP/UDP)的概念
- ICMP工作在网络层,不涉及端口号
- ICMP使用类型(Type)和代码(Code)区分消息
- ping使用Echo Request(类型8)和Echo Reply(类型0)
4.3 实战技能总结
学完本篇,你应该能够:
内网穿透相关:
- ✓ 使用frp实现内网穿透
- ✓ 远程SSH到家里的电脑
- ✓ 让朋友访问家里的网站
- ✓ 配置HTTP代理通过域名访问
- ✓ 使用systemd管理frpc服务
DNS相关:
- ✓ 使用dig工具分析域名解析
- ✓ 配置hosts文件
- ✓ 清除DNS缓存
- ✓ 理解浏览器输入URL后的完整过程
- ✓ 理解TTL的作用
ICMP相关:
- ✓ 使用ping测试网络连通性
- ✓ 使用traceroute诊断网络问题
- ✓ 理解TTL的含义
- ✓ 知道ping没有端口号
- ✓ 分析ping和traceroute的输出
4.4 网络系列总结
至此,网络部分的内容全部结束!
从应用层(HTTP、HTTPS)到传输层(TCP、UDP)到网络层(IP、ICMP、NAT)到数据链路层(以太网、ARP),再到进阶应用(代理、内网穿透、DNS),你已经掌握了完整的网络知识体系!
接下来可以开始实践了:
- 写网络程序(Socket编程)
- 搭建服务器(Nginx、frp)
- 优化性能(缓存、负载均衡)
- 诊断问题(ping、traceroute、dig)
把学到的知识应用到实际项目中!
💬 总结:这篇文章详细讲解了三大实战技术。内网穿透让我们能够突破NAT限制,远程访问家里的服务器,包含完整的frp部署教程。DNS域名解析系统让我们理解了域名如何转换为IP地址,掌握了dig工具的使用。ICMP协议让我们能够使用ping和traceroute诊断网络问题,特别强调了"ping不是端口"这个重要知识点。这些技术都非常实用,理解它们的原理能帮助你更好地搭建服务、诊断网络问题。至此,网络进阶系列全部完成!从NAT、代理到内网穿透、DNS、ICMP,你已经掌握了完整的网络进阶技能。接下来就是实践了——搭建服务、优化性能、解决问题,把学到的知识应用到实际项目中!
👍 点赞、收藏与分享:如果这篇内网穿透、DNS和ICMP的实战内容对你有帮助,特别是frp的完整部署教程、dig工具的使用、"浏览器输入URL后发生的事情"这道经典面试题的完整解答,请点赞收藏!网络进阶,从实战开始!
更多推荐



所有评论(0)