基于 IP 地址的地理位置判断,将中国 IP 段的请求转发到国内 DNS,美国 IP 段的请求转发到美国 DNS。
nginx.conf 中的部分代码:
# Nginx基于IP地理位置的DNS路由配置
# 根据客户端IP地址自动选择最优DNS服务器
stream {
# ========================================================
# 方法1:使用Nginx内置的geo模块(推荐)
# ========================================================
# geo模块专门用于基于IP地址的变量赋值
geo $client_country {
default global; # 默认使用全球DNS
# 中国IP地址段(部分示例)
# APNIC分配给中国的主要IP段
1.0.0.0/8 CN;
2.0.0.0/8 CN;
3.0.0.0/8 CN;
4.0.0.0/8 CN;
5.0.0.0/8 CN;
6.0.0.0/8 CN;
7.0.0.0/8 CN;
8.0.0.0/8 CN;
9.0.0.0/8 CN;
10.0.0.0/8 CN; # 私有地址,但通常在中国网络内
# 中国电信IP段
58.0.0.0/8 CN;
59.0.0.0/8 CN;
60.0.0.0/8 CN;
113.0.0.0/8 CN;
114.0.0.0/8 CN;
115.0.0.0/8 CN;
116.0.0.0/8 CN;
117.0.0.0/8 CN;
118.0.0.0/8 CN;
119.0.0.0/8 CN;
120.0.0.0/8 CN;
121.0.0.0/8 CN;
122.0.0.0/8 CN;
123.0.0.0/8 CN;
# 中国联通IP段
101.0.0.0/8 CN;
102.0.0.0/8 CN;
103.0.0.0/8 CN;
106.0.0.0/8 CN;
107.0.0.0/8 CN;
108.0.0.0/8 CN;
109.0.0.0/8 CN;
110.0.0.0/8 CN;
111.0.0.0/8 CN;
112.0.0.0/8 CN;
# 中国移动IP段
117.0.0.0/8 CN; # 与电信重叠
118.0.0.0/8 CN; # 与电信重叠
119.0.0.0/8 CN; # 与电信重叠
120.0.0.0/8 CN; # 与电信重叠
121.0.0.0/8 CN; # 与电信重叠
122.0.0.0/8 CN; # 与电信重叠
123.0.0.0/8 CN; # 与电信重叠
124.0.0.0/8 CN;
125.0.0.0/8 CN;
126.0.0.0/8 CN;
134.0.0.0/8 CN;
135.0.0.0/8 CN;
136.0.0.0/8 CN;
137.0.0.0/8 CN;
138.0.0.0/8 CN;
139.0.0.0/8 CN;
# 美国IP地址段(部分示例)
# ARIN分配给美国的主要IP段
64.0.0.0/8 US;
65.0.0.0/8 US;
66.0.0.0/8 US;
67.0.0.0/8 US;
68.0.0.0/8 US;
69.0.0.0/8 US;
70.0.0.0/8 US;
71.0.0.0/8 US;
72.0.0.0/8 US;
73.0.0.0/8 US;
74.0.0.0/8 US;
75.0.0.0/8 US;
76.0.0.0/8 US;
77.0.0.0/8 US;
78.0.0.0/8 US;
79.0.0.0/8 US;
80.0.0.0/8 US;
81.0.0.0/8 US;
82.0.0.0/8 US;
83.0.0.0/8 US;
84.0.0.0/8 US;
85.0.0.0/8 US;
86.0.0.0/8 US;
87.0.0.0/8 US;
88.0.0.0/8 US;
89.0.0.0/8 US;
90.0.0.0/8 US;
91.0.0.0/8 US;
92.0.0.0/8 US;
93.0.0.0/8 US;
94.0.0.0/8 US;
95.0.0.0/8 US;
96.0.0.0/8 US;
97.0.0.0/8 US;
98.0.0.0/8 US;
99.0.0.0/8 US;
100.0.0.0/8 US;
101.0.0.0/8 US; # 与中国联通重叠
102.0.0.0/8 US; # 与中国联通重叠
# 主要云服务商IP段
172.16.0.0/12 US; # AWS私有地址
10.0.0.0/8 US; # 私有地址,但常用于美国云服务
}
# 根据国家选择DNS服务器池
map $client_country $dns_pool {
CN dns_cn; # 中国IP使用国内DNS
US dns_us; # 美国IP使用美国DNS
default dns_global; # 其他国家使用全球DNS
}
# ========================================================
# 方法2:使用map模块的正则表达式匹配(备用方案)
# ========================================================
# 这种方法更灵活,但性能略低于geo模块
map $remote_addr $dns_pool_regex {
# 中国IP段正则匹配
~^1\.\d+\.\d+\.\d+$ dns_cn; # 1.0.0.0/8
~^2\.\d+\.\d+\.\d+$ dns_cn; # 2.0.0.0/8
~^3\.\d+\.\d+\.\d+$ dns_cn; # 3.0.0.0/8
~^4\.\d+\.\d+\.\d+$ dns_cn; # 4.0.0.0/8
~^5\.\d+\.\d+\.\d+$ dns_cn; # 5.0.0.0/8
~^11[3-9]\.\d+\.\d+\.\d+$ dns_cn; # 113.0.0.0/8 - 119.0.0.0/8
~^12[0-9]\.\d+\.\d+\.\d+$ dns_cn; # 120.0.0.0/8 - 129.0.0.0/8
~^10[1-3]\.\d+\.\d+\.\d+$ dns_cn; # 101.0.0.0/8 - 103.0.0.0/8
# 美国IP段正则匹配
~^6[4-9]\.\d+\.\d+\.\d+$ dns_us; # 64.0.0.0/8 - 69.0.0.0/8
~^7[0-9]\.\d+\.\d+\.\d+$ dns_us; # 70.0.0.0/8 - 79.0.0.0/8
~^8[0-9]\.\d+\.\d+\.\d+$ dns_us; # 80.0.0.0/8 - 89.0.0.0/8
~^9[0-9]\.\d+\.\d+\.\d+$ dns_us; # 90.0.0.0/8 - 99.0.0.0/8
# 默认使用全球DNS
default dns_global;
}
# ========================================================
# DNS服务器池定义
# ========================================================
# 国内DNS服务器池
upstream dns_cn {
least_conn; # 使用最少连接负载均衡
# 中国大陆DNS服务器
server 223.5.5.5:53 max_fails=3 fail_timeout=30s; # 阿里云DNS
server 223.6.6.6:53 max_fails=3 fail_timeout=30s; # 阿里云DNS备用
server 119.29.29.29:53 max_fails=3 fail_timeout=30s; # 腾讯云DNS
server 182.254.116.116:53 max_fails=3 fail_timeout=30s; # 腾讯云DNS备用
server 180.76.76.76:53 max_fails=3 fail_timeout=30s; # 百度DNS
server 114.114.114.114:53 max_fails=3 fail_timeout=30s; # 114DNS
server 114.114.115.115:53 max_fails=3 fail_timeout=30s; # 114DNS备用
# 备用服务器
server 8.8.8.8:53 backup; # 谷歌DNS作为备用
}
# 美国DNS服务器池
upstream dns_us {
least_conn; # 使用最少连接负载均衡
# 美国DNS服务器
server 8.8.8.8:53 max_fails=3 fail_timeout=30s; # 谷歌DNS
server 8.8.4.4:53 max_fails=3 fail_timeout=30s; # 谷歌DNS备用
server 1.1.1.1:53 max_fails=3 fail_timeout=30s; # Cloudflare DNS
server 1.0.0.1:53 max_fails=3 fail_timeout=30s; # Cloudflare DNS备用
server 9.9.9.9:53 max_fails=3 fail_timeout=30s; # Quad9 DNS
server 149.112.112.112:53 max_fails=3 fail_timeout=30s; # Quad9 DNS备用
server 208.67.222.222:53 max_fails=3 fail_timeout=30s; # OpenDNS
server 208.67.220.220:53 max_fails=3 fail_timeout=30s; # OpenDNS备用
# 备用服务器
server 223.5.5.5:53 backup; # 阿里云DNS作为备用
}
# 全球DNS服务器池(默认)
upstream dns_global {
least_conn; # 使用最少连接负载均衡
# 全球通用DNS服务器
server 8.8.8.8:53 max_fails=3 fail_timeout=30s; # 谷歌DNS
server 1.1.1.1:53 max_fails=3 fail_timeout=30s; # Cloudflare DNS
server 9.9.9.9:53 max_fails=3 fail_timeout=30s; # Quad9 DNS
server 223.5.5.5:53 max_fails=3 fail_timeout=30s; # 阿里云DNS
server 119.29.29.29:53 max_fails=3 fail_timeout=30s; # 腾讯云DNS
}
# ========================================================
# DNS代理服务器配置
# ========================================================
# DNS UDP代理(主要)
server {
listen 53 udp;
proxy_pass $dns_pool; # 使用geo模块的结果
# proxy_pass $dns_pool_regex; # 使用正则表达式的结果
proxy_timeout 10s;
proxy_responses 1;
proxy_buffer_size 16k;
# 故障转移配置
proxy_next_upstream error timeout;
proxy_next_upstream_tries 2;
# 访问日志(记录国家信息便于调试)
# access_log c:/nginx/logs/dns_udp_access.log '$remote_addr - $client_country - [$time_local] $protocol $status $bytes_sent $bytes_received';
# error_log c:/nginx/logs/dns_udp_error.log info;
}
# DNS TCP代理(辅助)
server {
listen 53;
proxy_pass $dns_pool;
proxy_timeout 10s;
# 故障转移配置
proxy_next_upstream error timeout;
proxy_next_upstream_tries 2;
# access_log c:/nginx/logs/dns_tcp_access.log '$remote_addr - $client_country - [$time_local] $protocol $status $bytes_sent $bytes_received';
}
# ========================================================
# 调试信息输出(可选)
# ========================================================
# 用于测试IP地理位置判断是否正确
server {
listen 8080;
return 'Client IP: $remote_addr\nCountry: $client_country\nDNS Pool: $dns_pool\n';
}
}
# ========================================================
# IP地址判断方法说明
# ========================================================
# 1. GEO模块方法(推荐)
# - 性能最好,专为IP地址匹配设计
# - 支持CIDR格式(如 1.0.0.0/8)
# - 支持从文件加载IP段(geo $client_country { include /path/to/geo.conf; })
#
# 2. MAP模块正则表达式方法
# - 更灵活,支持复杂的正则匹配
# - 性能略低于geo模块
# - 适合需要更复杂匹配规则的场景
#
# 3. 外部GeoIP数据库方法(企业级方案)
# - 使用MaxMind GeoIP2数据库
# - 需要编译Nginx时添加--with-http_geoip2_module
# - 配置示例:
# geoip2 /path/to/GeoLite2-Country.mmdb {
# $geoip2_country_code country iso_code;
# }
# map $geoip2_country_code $dns_pool {
# CN dns_cn;
# US dns_us;
# default dns_global;
# }
# ========================================================
# ========================================================
# 维护和更新建议
# ========================================================
# 1. IP地址段会定期更新,建议定期检查和更新
# 2. 可以从APNIC、ARIN等RIR获取最新的IP分配信息
# 3. 对于生产环境,建议使用专业的GeoIP数据库服务
# 4. 定期测试不同地区的DNS解析效果
# 5. 监控各DNS服务器的响应时间和成功率
# ========================================================