我来详细解释 DNS 和 ARP 的实现原理:
DNS(域名系统)实现
目的:将域名(如 www.example.com)转换为 IP 地址(如 192.0.2.1)
分层结构:
根域名服务器(.)
│
├── 顶级域名服务器(.com, .org, .cn)
│
└── 权威域名服务器(example.com)
│
└── 具体记录(www.example.com → 192.0.2.1)
简化的 DNS 查询流程
def dns_lookup(domain):
# 1. 检查本地缓存
if domain in local_cache:
return local_cache[domain]
# 2. 检查 hosts 文件
# 3. 查询本地 DNS 服务器
# 4. 递归/迭代查询
# 5. 获取结果并缓存DNS 报文结构: ┌─────────────────┐ │ Header │ # 事务ID、标志位、计数 ├─────────────────┤ │ Question │ # 查询的问题(域名、类型) ├─────────────────┤ │ Answer │ # 资源记录(答案) ├─────────────────┤ │ Authority │ # 权威服务器信息 ├─────────────────┤ │ Additional │ # 附加信息 └─────────────────┘
常见记录类型: A记录 - IPv4地址 AAAA记录 - IPv6地址 CNAME记录 - 别名 MX记录 - 邮件服务器 NS记录 - 域名服务器 TXT记录 - 文本信息
简化的 DNS 服务器代码结构
import socket
import struct
class DNSServer:
def __init__(self):
self.cache = {}
self.records = {
'www.example.com': {'type': 'A', 'value': '192.0.2.1'},
'mail.example.com': {'type': 'MX', 'value': '10 mail.example.com'}
}
def parse_dns_query(self, data):
# 解析 DNS 查询
header = struct.unpack('!HHHHHH', data[:12])
question = data[12:]
# 提取域名
domain_parts = []
pos = 0
while question[pos] != 0:
length = question[pos]
part = question[pos+1:pos+1+length]
domain_parts.append(part.decode())
pos += length + 1
domain = '.'.join(domain_parts)
return domain
def create_response(self, domain):
# 构建 DNS 响应
# ... 实现响应构建逻辑
pass
def start(self):
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(('', 53))
while True:
data, addr = server.recvfrom(512)
domain = self.parse_dns_query(data)
response = self.create_response(domain)
server.sendto(response, addr)ARP(地址解析协议)实现
目的:将 IP 地址转换为 MAC 地址(物理地址)
ARP 表(缓存):存储 IP-MAC 映射
def arp_resolve(target_ip):
# 1. 检查本地 ARP 缓存
if target_ip in arp_cache:
return arp_cache[target_ip]
# 2. 发送 ARP 请求(广播)
arp_request = create_arp_request(target_ip)
send_broadcast(arp_request)
# 3. 等待 ARP 响应
response = wait_for_arp_response(timeout=5)
# 4. 更新 ARP 缓存
if response:
arp_cache[target_ip] = response.mac_address
return response.mac_address
return None以太网帧头部: ┌─────────────────┬─────────────────┬─────────┐ │ 目的MAC(6字节) │ 源MAC(6字节) │ 类型 │ ├─────────────────┴─────────────────┴─────────┤ │ ARP 报文(28字节) │ │ ┌─────────────────────────────────────┐ │ │ │ 硬件类型(2) │ 协议类型(2) │ │ │ ├─────────────────────────────────────┤ │ │ │ 硬件地址长度│ 协议地址长度 │ │ │ ├─────────────────────────────────────┤ │ │ │ 操作码(2) │ │ │ ├─────────────────────────────────────┤ │ │ │ 发送方MAC地址(6) │ │ │ ├─────────────────────────────────────┤ │ │ │ 发送方IP地址(4) │ │ │ ├─────────────────────────────────────┤ │ │ │ 目标MAC地址(6) │ │ │ ├─────────────────────────────────────┤ │ │ │ 目标IP地址(4) │ │ │ └─────────────────────────────────────┘ │ └─────────────────────────────────────────────┘
import socket
import struct
import time
class ARPProtocol:
def __init__(self):
self.arp_table = {} # IP -> MAC 映射
self.pending_requests = {}
def create_arp_request(self, target_ip, src_ip, src_mac):
"""创建 ARP 请求包"""
# 以太网帧头
eth_header = struct.pack('!6s6sH',
b'\xff\xff\xff\xff\xff\xff', # 广播地址
src_mac, # 源MAC
0x0806) # ARP类型
# ARP 报文
arp_packet = struct.pack('!HHBBH6s4s6s4s',
0x0001, # 硬件类型:以太网
0x0800, # 协议类型:IPv4
6, # 硬件地址长度
4, # 协议地址长度
1, # 操作码:请求
src_mac, # 发送方MAC
src_ip, # 发送方IP
b'\x00'*6, # 目标MAC(未知)
target_ip) # 目标IP
return eth_header + arp_packet
def create_arp_reply(self, target_mac, target_ip, src_mac, src_ip):
"""创建 ARP 响应包"""
eth_header = struct.pack('!6s6sH',
target_mac, # 目标MAC
src_mac, # 源MAC
0x0806) # ARP类型
arp_packet = struct.pack('!HHBBH6s4s6s4s',
0x0001, # 硬件类型
0x0800, # 协议类型
6, # 硬件地址长度
4, # 协议地址长度
2, # 操作码:响应
src_mac, # 发送方MAC
src_ip, # 发送方IP
target_mac, # 目标MAC
target_ip) # 目标IP
return eth_header + arp_packet
def handle_arp_packet(self, data, src_mac):
"""处理收到的 ARP 包"""
# 解析 ARP 报文
arp_fields = struct.unpack('!HHBBH6s4s6s4s', data[14:42])
opcode = arp_fields[4]
sender_mac = arp_fields[5]
sender_ip = socket.inet_ntoa(arp_fields[6])
target_ip = socket.inet_ntoa(arp_fields[9])
# 更新 ARP 表
self.arp_table[sender_ip] = sender_mac
if opcode == 1: # ARP 请求
# 如果是询问我们的 IP,发送响应
if target_ip == self.local_ip:
reply = self.create_arp_reply(
sender_mac, sender_ip,
self.local_mac, self.local_ip
)
self.send_frame(reply)5.Gratuitous ARP(免费 ARP)
def send_gratuitous_arp(ip, mac):
"""发送免费 ARP 宣告自己的 IP-MAC 映射"""
# 源和目标 IP 都是自己的 IP
arp_packet = create_arp_request(ip, ip, mac)
send_broadcast(arp_packet)关键差异总结
| 特性 | DNS | ARP |
| 作用 | 域名→IP地址 | IP地址→MAC地址 |
| 工作层次 | 应用层 | 网络层/链路层 |
| 传输协议 | UDP/TCP(端口53) | 直接封装在以太网帧中 |
| 缓存 | DNS缓存(域名→IP) | ARP缓存(IP→MAC) |
| 查询范围 | 全局互联网 | 本地局域网 |
| 记录类型 | A、AAAA、CNAME等 | 只有IP-MAC映射 |
实际部署考虑
1、递归解析器:为用户提供 DNS 查询服务
2、权威服务器:管理特定域名的记录
3、缓存策略:TTL 控制缓存时间
4、安全机制:DNSSEC 防止缓存投毒
1、ARP 表管理:定时清理老化条目
2、ARP 欺骗防护:静态 ARP 绑定、ARP 监控
3、代理 ARP:路由器代为响应 ARP 请求
这两个协议是网络通信的基础,DNS 负责全局地址解析,ARP 负责局域网内的地址解析,它们共同确保网络数据能够正确路由到目标设备。
文章摘自:https://idc.huochengrm.cn/dns/23356.html
评论
脱南琴
回复DNS通过域名解析成IP地址,ARP通过IP地址查询物理地址,两者结合实现网络设备间通信。
和永福
回复DNS通过域名解析成IP地址,ARP通过IP地址查询MAC地址实现。