无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 6808|回复: 9
打印 上一主题 下一主题

android5.0到安卓10 dhcpv6客户端....

[复制链接]
跳转到指定楼层
1#
发表于 2021-5-28 01:35:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 510819776 于 2021-5-28 19:15 编辑

ipv6到来了,但是安卓手机居然不支持dhcpv6   
安卓只能支持 slaac 模式
我从chroot aarch64  3.13版本的alpine linux 中提取了 isc dhcp client 用来为安卓提供dhcp服务
dhclient -6 wlan0 -v 此命令获取新ipv6地址
dhclient -6 wlan0 -r -v 释放ipv6地址

使用很简单,下载附件,解压得到dhcp6文件夹
然后把dhcp6整个文件夹拷贝到手机/data下面
当然是需要root的
拷贝好打开终端模拟器
su
busybox chmod -R 777 /data/dhcp6
setenforce 0
/data/dhcp6/dhclient -6 wlan0 -v 即可
释放ip地址可以用
/data/dhcp6/dhclient -6 wlan -v -r即可
内置一个最新的dnsmasq 2.85版本
这个软件构架是aarch64  适合安卓5.0或以上版本
在我的红米note2 安卓5.0 和红米10x 5g 安卓10测试 正常使用
需要注意一下  这个dhclient 软件支持ipv4和ipv6
但是安卓的 dns4 dns6  设置和 linux终究不一样
安卓不使用/etc/resolv.conf
setipv6 这个文件其实是一个linux的shell脚本  
如果出现脚本报错情况 可以自己用文本编辑器修改setipv6大家可以对setipv6进行精简,这个脚本里面配置/etc/resolv.conf的命令部分可以删掉
安卓不使用/etc/resolv.conf来配置dns
这个获取ipv4 ipv6的软件 原理很简单
先用dhclient 来获取dhcp服务器的各种参数
然后 将这些参数全部保存成临时变量 之后借助setipv6脚本和系统自带的ip 以及其他命令来配置dhcpv6参数
对应到安卓 其实只有 写入ipv6地址有用  dns6由安卓自己完成(路由器设置的)
查看手机获取的dns6命令是  
getgrop | grep net.dns
ip查看命令是
busybox ifconfig wlan0



贴上自己精简后的setipv6




#!/data/dhcp6/busybox sh
ip=/system/bin/ip
#sleep=/system/xbin/sleep
#seq=/system/xbin/seq
#ifconfig=/system/xbin/ifconfig
_shellcheck_external_variables() {
    : alias_ip_address="$alias_ip_address"
    : alias_subnet_mask="$alias_subnet_mask"
    : cur_ip6_address="$cur_ip6_address"
    : cur_ip6_prefixlen="$cur_ip6_prefixlen"
    : dad_wait_time="$dad_wait_time"
    : interface="$interface"
    : new_broadcast_address="$new_broadcast_address"
    : new_dhcp6_domain_search="$new_dhcp6_domain_search"
    : new_dhcp6_name_servers="$new_dhcp6_name_servers"
    : new_domain_name="$new_domain_name"
    : new_domain_name_servers="$new_domain_name_servers"
    : new_host_name="$new_host_name"
    : new_interface_mtu="$new_interface_mtu"
    : new_ip6_address="$new_ip6_address"
    : new_ip6_prefixlen="$new_ip6_prefixlen"
    : new_ip_address="$new_ip_address"
    : new_max_life="$new_max_life"
    : new_preferred_life="$new_preferred_life"
    : new_rfc3442_classless_static_routes="$new_rfc3442_classless_static_routes"
    : new_routers="$new_routers"
    : new_subnet_mask="$new_subnet_mask"
    : old_dhcp6_domain_search="$old_dhcp6_domain_search"
    : old_dhcp6_name_servers="$old_dhcp6_name_servers"
    : old_host_name="$old_host_name"
    : old_ip6_address="$old_ip6_address"
    : old_ip6_prefixlen="$old_ip6_prefixlen"
    : old_ip_address="$old_ip_address"
    : reason="$reason"
}


exit_with_hooks() {
    local exit_status
    exit_status="${1}"
    exit "${exit_status}"
}

ipv6_addr_del() {

    "${ip}" -6 addr del "$@" dev "${interface}"

}

# shellcheck disable=SC2039
ipv6_addr_show() {
    local dev
    dev="${1}"

    "${ip}" -6 addr show ${dev:+dev "${dev}"}

}

# shellcheck disable=SC2039
ipv6_addr_filter() {
    local dev
    dev="${1}"
    shift
    ipv6_addr_show "${dev}" | grep -F -e "${*}"
}

# shellcheck disable=SC2039
ipv6_addr_has_tentative() {
    local dev
    dev="${1}"
    shift

    ipv6_addr_filter "${dev}" "${@}" | grep -F -e tentative >/dev/null 2>&1
}

ip_link_set() {

    ${ip} link set "${@}"

}

link_set_up() {
    ip_link_set dev "${interface}" up
}

link_set_mtu() {
    [ -n "${1}" ] || return 0

    ip_link_set dev "${interface}" mtu "${1}"
}

# shellcheck disable=SC2039
_ip_addr_flush() {

"${ip}" -6 addr flush "${@}"

}


ipv6_addr_flush() {
    _ip_addr_flush "$@"
}


add_ipv6_addr_with_DAD() {

    local _i
  "${ip}" -6 addr replace "${new_ip6_address}/${new_ip6_prefixlen}" \
        dev "${interface}" scope global valid_lft "${new_max_life}" \
        preferred_lft "${new_preferred_life}"
    if [ "${dad_wait_time}" -le 0 ]; then

        return 0
    fi

    for _i in $(/data/dhcp6/busybox seq 1 "${dad_wait_time}"); do
        /data/dhcp6/busybox sleep 1

        addr="$(ipv6_addr_filter "${interface}" \
            "${new_ip6_address}/${new_ip6_prefixlen}")"

        tentative="$(echo "${addr}" | grep tentative)"

        dadfailed="$(echo "${addr}" | grep dadfailed)"

        if [ -n "${dadfailed}" ]; then

            ipv6_addr_del "${new_ip6_address}/${new_ip6_prefixlen}"

            exit_with_hooks 3
        fi

        if [ -z "${tentative}" ]; then
            if [ -n "${addr}" ]; then

                return 0
            else
                exit_with_hooks 3
            fi
        fi
    done

    return 0
}

# shellcheck disable=SC2039
init_if_metric() {
    local _if_metric
    _if_metric="${IF_METRIC}"
    if [ "${new_routers%% *}" != "${new_routers}" ]; then
        _if_metric="${_if_metric:-1}"
    fi
    if_metric="${_if_metric}"
    echo "${_if_metric}"
}

case "${reason}" in


        PREINIT)
        echo
       
                ;;

    PREINIT6)

        #print_dhcp_info
        interface_up_wait_time=5
        for _i in $(/data/dhcp6/busybox seq 0 ${interface_up_wait_time}); do
            if /data/dhcp6/busybox ifconfig "${interface}" | grep RUNNING >/dev/null 2>&1; then
                break
            fi
            /data/dhcp6/busybox sleep 1
        done; unset -v _i
        ipv6_addr_flush dev "${interface}" scope global permanent

        if [ "${dad_wait_time}" -gt 0 ]; then

            if ipv6_addr_has_tentative "${interface}" inet6; then

                for _i in $(seq 0 "${dad_wait_time}"); do
                   /data/dhcp6/busybox sleep 1
                    if ! ipv6_addr_has_tentative "${interface}" inet6; then
                        break
                    fi
                done; unset -v _i
            fi
        fi


        ;;

    BOUND6|RENEW6|REBIND6)
        if [ "${new_ip6_address}" ] && [ "${new_ip6_prefixlen}" ]; then
            add_ipv6_addr_with_DAD
        fi

        ;;

    DEPREF6)
        if [ -z "${cur_ip6_prefixlen}" ]; then
            exit_with_hooks 2
        fi
        "${ip}" -6 addr change "${cur_ip6_address}/${cur_ip6_prefixlen}" \
            dev "${interface}" scope global preferred_lft 0

        ;;

    EXPIRE6|RELEASE6|STOP6)
        if [ -z "${old_ip6_address}" ] || [ -z "${old_ip6_prefixlen}" ]; then
            exit_with_hooks 2
        fi
        ipv6_addr_del "${old_ip6_address}/${old_ip6_prefixlen}"

        ;;
esac
echo "$reason"
#print_dhcp_info
busybox ifconfig "${interface}" | busybox grep inet
getprop | grep net.dns
exit_with_hooks 0

android的dns v6很神奇,不知道怎么搞的
./dhclient -6 wlan0 -v 执行两次后
getprop | grep net.dns 命令可以看到
net.dns1 net.dns2自动变成了 路由器里面的dns6地址
但这应该与脚本无关吧




路由器是openwrt  使用dnsmasq提供dhcp v6服务

这是我对ipv6 dnsmasq不成熟的一点理解
###################################################################
#运行dnsmasq的服务器ip设置为2::1/64,剩余64位客户端根据某些算法自动填充,无状态dhcp
dnsmasq -u root -i br-lan -h -K -n -N -R --dhcp-no-override -F 2::2,2::9,slaac --port=0 --dhcp-option=option6:dns-server,[8::8],[8::4]
这个命令适合安卓,ios支持dhcpv6 win支持dhcpv6 linux  mac都支持dhcpv6

#运行dnsmasq的服务器ip设置为2::1/112,有状态dhcp
#dnsmasq -u root -h -K -n -N -R -i br-lan -F 2::2,2::9,112,10m --dhcp-no-override --enable-ra --port=0 --dhcp-option=option6:dns-server,[8::8],[8::4]
这个命令安卓是无法获取到ipv6地址的
但是可以用dhclient 或 wide dhcpv6 client 获取到ipv6地址
安卓busybox udhcpc6命令会崩溃....


#运行dnsmasq的服务器ip设置为2::1/112,静态指定ipv6地址
#客户端duid获取方式,前台运行dnsmasq后l可以看到duid信息
#duid windows可以直接ipconfig /all查看

静态ipv6指定
#dnsmasq -u root -i enp0s25 -h -K -n -N -R --dhcp-no-override --dhcp-sequential-ip --port=0 -F 2::2,2::9,112,100m --enable-ra --dhcp-host=id:00:01:00:01:28:41:4f:af:08:00:27:a2:03:a3,[2::33]  
此命令执行前删除/var/lib/misc/dnsmasq.leases
除非是slaac,无状态配置,否则要加上--enable-ra参数,不加虽能获取ip,但ping不通


#dnsmasq -u root -i enp0s25 -h -K -n -N -R --dhcp-no-override --dhcp-sequential-ip --port=0 --dhcp-host=id:00:01:00:01:28:41:4f:af:08:00:27:a2:03:a3,[2::33] --enable-ra
这个命令应该也行,不过由于duid 会动态变化,一般不建议锁死ipv6



-h  --no-host
-K  --dhcp-authoritative
-n  --no-poll
-N  --no-negcache
-R  --no-resolv
--dhcp-sequential-ip

安卓客户端可使用dhclient -6 wlan0 获取dhcpv6地址
也可以用wide-dhcpv6-client中的dhcp6c -i wlan0获取dhcpv6地址

################################################


附件下载   
dhcp6.7z (1.85 MB, 下载次数: 6)



2#
发表于 2021-5-28 08:46:42 | 只看该作者
非要安卓支持有状态v6没啥意义吧,如果是要做服务器那直接自定义好了,windows有状态地址时候也会分配一个自动生成的无状态地址用的呀。

点评

用我这个教程 安卓手机可以获取到 诸如 2::x/128 这样的ipv6地址 其中x 是从2到9 方便用ipv6地址来访问手机 如果用无状态的slaac 分配到的是一个前缀为64的半随机ipv6地址 超级长 类似 xxxx:yyyy:zzzz:uuuu:  详情 回复 发表于 2021-5-28 16:42
回复

使用道具 举报

3#
发表于 2021-5-28 08:57:50 | 只看该作者
good
回复

使用道具 举报

4#
发表于 2021-5-28 10:42:39 | 只看该作者
感谢楼主经典技术文章
回复

使用道具 举报

5#
 楼主| 发表于 2021-5-28 16:42:41 | 只看该作者
本帖最后由 510819776 于 2021-5-28 17:17 编辑
pengfangzhi 发表于 2021-5-28 08:46
非要安卓支持有状态v6没啥意义吧,如果是要做服务器那直接自定义好了,windows有状态地址时候也会分配一个 ...

用我这个教程  安卓手机可以获取到诸如
2::x/128  这样非常短 的ipv6地址  其中x 是从2到9  方便用ipv6地址来访问手机

然后就是 ios  linux windows mac 全部都支持dhcpv6 就安卓不支持这安卓就是个奇葩了  人家都支持 就你不支持  用无意义来当借口是苍白的


回复

使用道具 举报

6#
发表于 2021-8-5 15:27:04 | 只看该作者
不支持ipv6? 来学习一下
回复

使用道具 举报

7#
发表于 2023-1-6 09:46:56 来自手机 | 只看该作者
??? alpine linux  glibcbionicС磩
回复

使用道具 举报

8#
发表于 2023-1-6 09:47:54 来自手机 | 只看该作者
?alpine linux 安卓能跑?
回复

使用道具 举报

9#
发表于 2023-1-13 11:14:57 | 只看该作者
多谢楼主热心提供安卓系统的教程啊,看看这个帖子,学习学习
回复

使用道具 举报

10#
发表于 2023-3-28 16:55:14 | 只看该作者
6666
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2025-12-18 20:06

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表