博客

  • 局域网名字解析和服务发现协议对比

    • mdns(Multicast DNS)/dns-sd(DNS Service Discovery)
      支持名字解析和服务发现,由苹果公司最早提出,苹果所有设备和Windows10以上版本默认支持mdns协议,Ubuntu/debian通过libnss的插件nss-mdns提供支持,但没有默认启用。
      mdns使用组播协议进行名字解析,解析到的名字统一放到.local域下。dns-sd是mdns的扩展,与mdns兼容,不但支持组播还支持使用单播进行解析,可以配置自定义域名后缀并与DNS服务器配置完成域名解析,更适合企业环境中使用。
      mdns/dns-sd使用UDP协议,5353端口。
    • SSDP(upnp)
      仅服务发现,没有名字解析功能,ssdp是upnp的组成部分,支持IPv4和IPv6。使用HTTPU/HTTPMU(基于UDP) 1900端口。UPNP提供了设备和服务发现,设备信息获取,设备控制功能,甚至提供了NAT穿透功能,可以作为智能家居设备的底层协义,DLNA投屏协义也是基于UPNP。
    • NBNS(NetBIOS Name Service)/WINS
      不支持IPv6,已经废弃。NetBIOS是一项古老的协议,由IBM开发。WINS是由微软开发的基于NBNS的协议,WINS支持单播,而且支持域名后缀并与DNS服务器集成,更适合企业环境中使用,类似dns-sd与mdns的关系。Windows10以上版本已经废弃NetBIOS的服务发现功能,取而代之的是WSSD和LLMNR(MDNS的支持似乎还不完整,只有名字解析,没有服务发现)。
      nbns/wins使用UDP/TCP协议,137端口。
    • LLMNR(Link-Local Multicast Name Resolution)
      也是提供基于多播协议的DNS解析功能,但仅提供名字解析,没有服务发现功能,与mdns非常类似,由微软件开发因未竞争过mdns所以未成为正式IETF正式标准。LLMNR使用UDP 5355端口。自 2022 年 4 月起,微软已开始逐步淘汰 LLMNR 和NetBIOS名称解析,转而使用mDNS。LLMNR落败的主要原因是没有与普通DNS解析的名称进行区分,导致LLMNR的名字会污染普通的DNS名字造成安全隐患,mdns则是用.local后缀作区分。
    • DDNS(Dynamic Updates in the Domain Name System)
      即动态DNS,与DHCP配合使用,由DHCP服务器把主机名注册到DNS服务器。缺点是静态IP地址就没法用了。

    参考:
    LLMNR
    https://datatracker.ietf.org/doc/rfc4795/
    这篇文章讲解了LLMNR与MDNS的竞争
    https://www.eiman.tv/blog/posts/lannames/
    Multicast DNS
    https://datatracker.ietf.org/doc/rfc6762/
    DNS Service Discovery
    https://datatracker.ietf.org/doc/rfc6763/
    http://www.dns-sd.org/
    DDNS
    https://datatracker.ietf.org/doc/rfc2136/
    libnss的d-bus接口
    https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.resolve1.html
    cups支持systemd-dnssd的issue
    https://github.com/OpenPrinting/libcups/issues/81
    wikipedia的介绍
    https://en.wikipedia.org/wiki/Zero-configuration_networking

    Views: 76

  • 华为路由器PPPOE拨号IPv6不稳定

    表现为IPv6速度慢,有的网站能打开,有的打不开。

    #pppoe口
    int Dialer 1
      mtu 1492
      ipv6 mtu 1492
    #lan口
    int vlanif 2
      mtu 1492
      ipv6 mtu 1492
    

    造成这种问题是原因多方面的:
    – IPv6天生不允许分片
    – 华为路由器的MTU,IPv4和IPv6是分开配置的,PPPOE会自动配置IPv4的MTU为1492,但IPv6不会
    – ipv6 pathmtu被某些设备破坏了或者某些网站pathmtu不正确

    正常情况下IPv6是不需要设置MTU的,IPv6始终使用Path MTU Discovery自动发现正确的MTU,出现这种情况大概率华为设备的PMTUD协议有问题,这种问题仅在华为设备上出现。
    OpenWrt就是有项RA MTU的设置,会把PPPOE接口的MTU通告给下游设备。

    参考:
    https://macgeeker.com/openwrt/ipv6-mtu/
    https://forum.huawei.com/enterprise/zh/thread/blog/703813366742663168

    Views: 4

  • 端口映射协议介绍

    • UPNP IGD V1
      随UPNP于1999年发布,IGD作为UPNP的组成部分提供了添加和删除端口映射,分配租约时间,枚举现有端口映射,了解公共外部IP地址功能,现有的IGD V1实现存在安全漏洞。此为ISO标准,非IETF标准。现已被IGE V2取代
    • UPNP IGD V2
      于2010年发布,增加了IPV6支持,并纠正了值为 0 的无限租用时间的误解。但与微软IGD V1客户端存在兼容性问题。ISO标准,非IETF标准。
    • NAT-PMP
      由IETF定义,是一个独立的端口映射协议,2005年由苹果推出。现已被PCP取代。
      https://datatracker.ietf.org/doc/rfc6886/
    • PCP(Port Control Protocol)
      是NAT-PMP的升级,于2013年公布RFC,支IPv6,支持在CGN和家庭环境中使用,支持生命期管理。
      https://datatracker.ietf.org/doc/rfc6887/

    未来PCP有可能取代其它几种协议

    UPNP+(2.0)已于2015年发布
    https://openconnectivity.org/developer/specifications/upnp-resources/upnp/

    Views: 5

  • python使用协程循环并发执行http请求

    import asyncio
    import aiohttp
    
    async def do_request(val):
        timeout = aiohttp.ClientTimeout(total=86400)
        async with aiohttp.ClientSession(timeout=timeout) as session:
            async with session.post('http://127.0.0.1:5000'), json={"val": val}) as resp:
            result = await resp.json()
            return result
    
        async def main(count):
            tasks = [do_request(val) from val in range(count)]
            values = await asyncio.gather(*tasks)
            print(values)
    
    asyncio.run(main(10))
    

    参考:
    https://superfastpython.com/asyncio-for-loop/
    https://www.dongwm.com/post/understand-asyncio-1/
    https://www.dongwm.com/post/understand-asyncio-2/

    Views: 2

  • dnsdist降低健康检查的频率

    dnsdist默认会以1Hz的频率向上游服务器发送a.root-servers.net的解析请求,用于健康检查,下面配置10分钟发送一次
    newServer({address="172.30.0.54", pool="rec", checkInterval=600})

    Views: 2

  • dnsdist支持ipv6

    dnsdist.conf中按下面配置,同时Docker开启ipv6支持

    addLocal('0.0.0.0', {reusePort=true,doTCP=true})
    addLocal('::', {reusePort=true,doTCP=true})
    setACL({'0.0.0.0/0', '::/0'})
    webserver("0.0.0.0:8083")
    webserver("[::]:8083")
    

    Views: 1

  • openwrt流量监控

    opkg install luci-app-nlbwmon luci-i18n-nlbwmon-zh-cn nlbwmon

    参考:
    https://github.com/destan19/OpenAppFilter
    https://github.com/jow-/nlbwmon/tree/master

    Views: 2

  • automake交叉编译

    export PATH=$PATH:/opt/toolchains/taowrt-toolchain-1.0.4-mediatek-filogic_gcc-13.3.0_musl.Linux-x86_64/toolchain-aarch64_cortex-a53_gcc-13.3.0_musl/bin/
    ./configure --build=aarch64-openwrt-linux
    make
    

    Views: 1

  • 关于nftables在output hook中设置mark路由不通的问题

    我这里排查到两点原因
    1. output hook只能是rotue链,不能是filter链,而prerouting则只能是filter链
    要这样写
    nft add chain inet fw4 gfw_output { type route hook output priority mangle\; policy accept\; }
    filter的优先级是比route低的
    官方是这么写的

    filter: Supported by arp, bridge, ip, ip6 and inet table families.
    route: Mark packets (like mangle for the output hook, for other hooks use the type filter instead), supported by ip and ip6.
    nat: In order to perform Network Address Translation, supported by ip and ip6.
    2. 本地出口源IP的问题
    可能因为默认路由在wan口上,所以本地发包源IP始终是wan口上的IP,而这个IP是运营商分配的100.64.0.0/10段的IP,这样就导致远端服务器找不到到100.64.0.0/10的路由,数据包有去无回,需要在服务器上配置这个网段的路由
    如果是wireguard在AllowedIPs中添加100.64.0.0/10网段即可。

    参考:
    https://forums.gentoo.org/viewtopic-t-1136379-start-0.html

    Views: 17

  • 计算udp校验和(反码求和)

    C语言1:

    #include <stdio.h>
    #include <arpa/inet.h>
    
    unsigned long checksum(char *buf,int nword)
    {
        unsigned long sum;
        unsigned short *data = (unsigned short *) buf;
    
        for(sum=0; nword>0; nword--)
        {
            sum += *data;
            data++;
            sum = (sum>>16) + (sum&0xffff);
        }
        sum = ~checksum & 0xFFFF;
        return htons(sum); //转为大端字节序
    }
    
    void main(int argc, char *argv[])
    {
        char b []  = "\0d\0e";
        unsigned long ret = checksum(b, 2);
        printf("checksum is: 0x%lx\n", ret);
        printf("checksum is: %lu\n", ret);
    
    }
    

    C语言2(github copilot):

    #include <stdio.h>
    #include <stdint.h>
    
    uint16_t udp_checksum(uint8_t *data, size_t len) {
        uint32_t checksum = 0;
    
        // 如果数据长度是奇数,填充一个字节
        if (len % 2 != 0) {
            data[len] = 0;
            len++;
        }
    
        // 将字节数组分成16位的块并相加
        for (size_t i = 0; i < len; i += 2) {
            uint16_t word = (data[i] << 8) + data[i + 1];
            checksum += word;
            // 处理进位
            checksum = (checksum & 0xFFFF) + (checksum >> 16);
        }
    
        // 取反码
        checksum = ~checksum & 0xFFFF;
        return (uint16_t)checksum;
    }
    
    int main() {
        uint8_t data[] = {'a', 'b', 'c', 'd'};
        size_t len = sizeof(data) / sizeof(data[0]);
        printf("Checksum: 0x%04X\n", udp_checksum(data, len));
        return 0;
    }
    

    Python(Github copilot):

    def udp_checksum(data):
        """下面是一个用Python编写的UDP校验和算法:
        ### 步骤:
        1. 定义一个函数 `udp_checksum`,接受一个字节数组作为参数。
        2. 将字节数组分成16位的块。
        3. 将所有16位块相加。
        4. 如果有进位,则将进位加到结果中。
        5. 取结果的反码。
        6. 返回低16位,就是校验和。
        """
        if len(data) % 2 != 0:
            data += b'\x00'  # 如果数据长度是奇数,填充一个字节
    
        checksum = 0
        for i in range(0, len(data), 2):
            # 这个公式是大端的算法,如果是小端可以写作(data[i+1] << 8) + data[i]
            word = (data[i] << 8) + data[i + 1]
            print(word)
            checksum += word
            checksum = (checksum & 0xFFFF) + (checksum >> 16)  # 处理进位
    
        checksum = ~checksum & 0xFFFF  # 取反码
        return checksum
    
    # 示例用法
    data = b'\0d\0e'
    print(hex(udp_checksum(data)))  # 输出校验和
    

    关于接收端验证的方法:

    把整个需要校验的数据计算校验和(反码求和),如果结果为0x0000则结果就是正确的,或者计算原码求和(累加后不取反),结果为0xffff则就是正确的。网上有的说验证结果为0x0000,有的说验证结果为0xffff要了解其中的原因。

    参考:
    https://blog.csdn.net/weixin_28673511/article/details/130314065
    https://zhuanlan.zhihu.com/p/74381973

    Views: 2