Android DNS切换SH脚本需修改/etc/resolv.conf,需ROOT权限,重启网络生效
安卓系统DNS切换SH脚本详解与实践指南
在移动互联网时代,DNS(域名系统)作为网络访问的"导航仪",直接影响着设备的网络访问速度和稳定性,安卓系统用户常遇到网络卡顿、特定网站无法访问等问题,通过修改DNS服务器可以有效改善这些状况,本文将详细介绍如何在安卓设备上使用SH脚本实现智能DNS切换,包含原理分析、脚本编写、实战应用等内容。
DNS基础知识
概念 | 说明 |
---|---|
DNS作用 | 将域名转换为IP地址的分布式数据库系统 |
公共DNS | 谷歌(8.8.8.8)、Cloudflare(1.1.1.1)、阿里(223.5.5.5)等第三方服务 |
运营商DNS | 由网络服务提供商分配的本地DNS(通常自动获取) |
DNS加密 | DNS over HTTPS/TLS(DoH/DoT)协议实现传输加密 |
常见DNS对比表
DNS服务商 | IP地址 | 特点 | 适用场景 |
---|---|---|---|
8.8.8 | 全球覆盖,响应快 | 国际网站访问 | |
Cloudflare | 1.1.1 | 隐私保护,抗DDoS | 注重隐私的用户 |
阿里 | 5.5.5 | 国内优化,稳定 | 访问国内主流网站 |
腾讯 | 29.29.29 | 游戏加速,低延迟 | 游戏玩家 |
OpenDNS | 67.222.222 | 家庭友好,安全过滤 | 儿童设备 |
安卓系统DNS配置方式
常规设置路径
- 图形界面:设置 → 网络 → DNS → 手动输入
- ADB命令:
adb shell setprop net.dns1 [IP]
SH脚本优势
对比维度 | 图形界面 | SH脚本 |
---|---|---|
自动化程度 | 低(需手动操作) | 高(可定时/事件触发) |
批量处理 | 不支持 | 支持多设备批量部署 |
灵活性 | 固定配置 | 可编程动态切换 |
日志记录 | 无 | 支持操作日志 |
SH脚本编写核心要素
基础命令结构
#!/system/bin/sh # DNS切换脚本 by YourName # 获取当前网络类型 NETWORK_TYPE=$(dumpsys connectivity | grep "defaultNetwork" | awk '{print $2}') # 根据网络类型选择DNS case "$NETWORK_TYPE" in "WIFI") NEW_DNS="223.5.5.5" ;; "DEFAULT") # 移动数据 NEW_DNS="114.114.114.114" ;; *) NEW_DNS="8.8.8.8" ;; esac # 应用新DNS配置 ifconfig "$INTERFACE" down sed i "s/^dns1=.*/dns1=$NEW_DNS/" /etc/ppp/ipup ifconfig "$INTERFACE" up
关键参数说明
参数名 | 作用 | 示例值 |
---|---|---|
$INTERFACE |
网络接口名称 | rmnet_data0 |
dns1 |
主DNS服务器配置项 | 8.8.8 |
dns2 |
备用DNS服务器配置项 | 8.4.4 |
高级功能扩展
(1) 定时切换功能
# 每天凌晨2点切换DNS (crontab l ; echo "0 2 * * * /data/local/dns_switch.sh") | sort | crontab
(2) 测速智能选择
# 定义测速函数 function speedtest() { ping c 5 $1 | tail n 2 | awk '{sum+=$6} END {print sum/5}' } # 测试各DNS延迟 wifi_speed=$(speedtest 223.5.5.5) mobile_speed=$(speedtest 114.114.114.114) # 选择最优DNS if [ "$wifi_speed" lt "$mobile_speed" ]; then NEW_DNS="223.5.5.5" else NEW_DNS="114.114.114.114" fi
完整脚本示例与部署
脚本代码(带注释)
#!/system/bin/sh # DNS智能切换脚本 v2.0 # 作者:YourName # 功能:根据网络类型和延迟自动选择最优DNS # 配置参数区 WIFI_DNS="223.5.5.5" # WiFi推荐DNS MOBILE_DNS="114.114.114.114" # 移动网络推荐DNS DEFAULT_DNS="8.8.8.8" # 默认DNS LOG_FILE="/data/dns.log" # 日志文件路径 # 获取当前网络状态 get_network_status() { CURRENT_NET=$(dumpsys connectivity | grep "defaultNetwork" | awk '{print $2}') } # 日志记录函数 log() { echo "$(date +"%Y%m%d %H:%M:%S") $1" >> $LOG_FILE } # Ping延迟测试函数 ping_test() { ping c 4 $1 | awk '/rtt/ {sum+=$5} END {printf "%.2f ", sum/4}' } # 主执行流程 get_network_status case "$CURRENT_NET" in "WIFI") PRIMARY_DNS=$WIFI_DNS ;; "DEFAULT") PRIMARY_DNS=$MOBILE_DNS ;; *) PRIMARY_DNS=$DEFAULT_DNS ;; esac # 测试主备DNS延迟 PRIMARY_LATENCY=$(ping_test $PRIMARY_DNS) SECONDARY_LATENCY=$(ping_test ${DEFAULT_DNS}) # 选择最优DNS if [ $(echo "$PRIMARY_LATENCY > $SECONDARY_LATENCY" | bc) eq 1 ]; then ACTUAL_DNS=${DEFAULT_DNS} else ACTUAL_DNS=$PRIMARY_DNS fi # 应用DNS配置 log "Switching DNS to $ACTUAL_DNS" sed i "s/^dns1=.*/dns1=$ACTUAL_DNS/" /etc/ppp/ipup ifconfig "$INTERFACE" down sleep 2 ifconfig "$INTERFACE" up log "DNS switch completed successfully"
部署步骤
步骤序号 | 操作说明 | 注意事项 |
---|---|---|
1 | 创建脚本文件:vi /data/local/dns_switch.sh |
确保文件具有执行权限 |
2 | 添加执行权限:chmod +x /data/local/dns_switch.sh |
需要root权限 |
3 | 测试脚本:sh /data/local/dns_switch.sh |
观察日志输出 |
4 | 设置开机自启:将脚本添加到/etc/init.d/ 目录 |
需要root权限 |
5 | 验证效果:通过ipconfig 或nmcli 查看DNS配置变化 |
确保网络接口名称正确 |
常见问题与解决方案
问题1:脚本执行后DNS未生效
可能原因:
- 网络接口名称错误(应为rmnet_data0/wlan0等)
- 配置文件路径不准确(不同ROM可能有差异)
- SELinux安全策略限制
解决方法:
- 使用
ifconfig
命令确认接口名称 - 检查
/etc/ppp/ipup
是否存在且可写 - 临时关闭SELinux:
setenforce 0
(需root)
问题2:定时任务不执行
可能原因:
- crontab服务未启动(部分安卓精简版系统)
- 脚本路径包含空格或特殊字符
- 系统休眠导致任务中断
解决方法:
- 手动启动crond服务:
/system/bin/crond
- 使用绝对路径并添加引号:
"/data/local/dns_switch.sh"
- 设置唤醒锁:在脚本开头添加
wakelock
相关代码
相关问题与解答
Q1:如何在不同安卓版本实现DNS切换?
A:Android 10+建议使用Settings.Global.PRIVATE_DNS
系统设置,通过settings put global private_dns_mode provider
启用,对于旧版本,可通过修改/system/etc/dhcpcd.conf
或使用VPN模式实现,具体方法如下:
# Android 10+专用方案 settings put global private_dns_mode "provider" settings put global private_dns_specifier "hostname=1.1.1.1"
Q2:如何验证DNS切换是否成功?
A:可通过以下三种方式验证:
- 命令行检测:
ping c 3 www.baidu.com
观察解析IP地址 - 抓包分析:使用Wireshark捕获DNS查询请求包头信息
- 在线检测:访问https://www.whatsmydns.net