Example #1
0
def download(req):
    #显式加载 CA,确保正常使用
    global context
    if context is None:
        import ssl
        context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
        context.verify_mode = ssl.CERT_REQUIRED
        context.set_ciphers(ssl._RESTRICTED_SERVER_CIPHERS)
        context.load_verify_locations(ca1)
        context.load_verify_locations(ca2)
    retry_delay = 2
    timeout = 8
    l = 0
    while l is 0:
        fd = None
        try:
            fd = urllib.request.urlopen(req, timeout=timeout, context=context)
            l = int(fd.headers.get('Content-Length', 0))
        except:
            pass
        if l is 0:
            if fd:
                fd.close()
            log('链接直连 IP 库网址失败,%d 秒后重试' % retry_delay)
            from time import sleep
            sleep(retry_delay)
    return fd, l
Example #2
0
def download_both_cniplist_as_db(ipdb):
    log('开始下载 APNIC 和 17mon IP')
    global update
    _iplist = download_cniplist(ipdb, parse_apnic_cniplist)
    _update = update
    iplist = download_cniplist(ipdb, parse_17mon_cniplist)
    iplist.extend(_iplist)
    update = '%s and %s' % (_update, update)
    save_iplist_as_db(ipdb, iplist)
    log('APNIC 和 17mon IP 已保存完毕')
Example #3
0
def download_cniplist(ipdb, parse_cniplist):
    #支持断点续传
    global Req_APNIC, Req_17MON, update
    if parse_cniplist is parse_apnic_cniplist:
        if Req_APNIC is None:
            Req_APNIC = req = urllib.request.Request(Url_APNIC)
        update = None
        name = 'APNIC'
    elif parse_cniplist is parse_17mon_cniplist:
        if Req_17MON is None:
            Req_17MON = req = urllib.request.Request(Url_17MON)
        import time
        #设定为当月第一天
        update = '17mon-' + time.strftime('%Y%m01', time.localtime(
            time.time()))
        name = '17mon'
    req.remove_header('Range')
    read = 0
    l = None
    while read != l:
        fd, _l = download(req)
        if l is None:
            l = _l
        iplist, _read = parse_cniplist(fd)
        if _read is None:
            read = l
        else:
            read += _read
        fd.close()
        #下载失败续传
        if read != l:
            #往回跳过可能的缺损条目
            read = max(read - 100, 0)
            req.remove_header('Range')
            req.add_header('Range', 'bytes=%d-' % read)
            log('%s IP 下载中断,续传:%d/%d' % (name, read, l))
    log(name + ' IP 下载完毕')
    return iplist
Example #4
0
def save_iplist_as_db(ipdb, iplist):
    #    +---------+
    #    | 4 bytes |                     <- data length
    #    +---------------+
    #    | 224 * 4 bytes |               <- first ip number index
    #    +---------------+
    #    |  2n * 4 bytes |               <- cn ip ranges data
    #    +------------------------+
    #    | b'end' and update info |      <- end verify
    #    +------------------------+
    lastip_s = 0
    lastip_e = 0
    index = g_index
    index_n = 0
    index_fip = -1
    offset = 0
    iplist.extend(keeplist)
    #排序,不然无法处理
    iplist.sort(key=lambda x: x[0])
    #随便算一下
    buffering = len(iplist) * 8 + 224 * 4 + 64 + 4
    buffer = bytearray(buffering)
    for ip, mask in iplist:
        ip_s = ip >> mask << mask
        ip_e = (ip >> mask) + 1 << mask
        #判断连续
        if ip_s <= lastip_e:
            #判断覆盖
            if ip_e > lastip_e:
                lastip_e = ip_e
            continue
        #排除初始值
        if lastip_e:
            #一段范围分为包含和排除
            buffer[offset:] = lastip_s = int2bytes4(lastip_s)
            buffer[offset + 4:] = int2bytes4(lastip_e)
            #一个索引分为开始和结束
            fip = lastip_s[0] * 2
            if fip != index_fip:
                #前一个索引结束,序数多 1
                #避免无法搜索从当前索引结尾地址到下个索引开始地址
                index[index_fip + 1] = index_b = int2bytes2(index_n)
                #当前索引开始
                index[fip] = index_b
                index_fip = fip
            index_n += 2
            offset += 8
        lastip_s = ip_s
        lastip_e = ip_e
    #添加最后一段范围
    buffer[offset:] = lastip_s = int2bytes4(lastip_s)
    buffer[offset + 4:] = int2bytes4(lastip_e)
    fip = lastip_s[0] * 2
    if fip != index_fip:
        index[index_fip + 1] = index_b = int2bytes2(index_n)
        index[fip] = index_b
    index_n += 2
    offset += 8
    #添加最后一个结束索引
    index[fip + 1] = int2bytes2(index_n)
    #写入文件
    fd = open(ipdb, 'wb', buffering)
    fd.write(int2bytes4(offset))
    padding = g_padding
    for i in range(224 * 2):
        fd.write(index.get(i, padding))
    fd.write(buffer[:offset])
    fd.write(b'endCN IP from ')
    fd.write(update.encode('ascii'))
    fd.write(b', range count: ')
    count = str(index_n // 2)
    fd.write(count.encode('ascii'))
    fd.close()
    #清空缓存
    g_iplist_apnic.clear()
    g_iplist_17mon.clear()
    g_index.clear()
    log('更新信息:%s' % update)
    log('包含 IP 范围条目数:%s' % count)
    log('保存地址:%s' % ipdb)
Example #5
0
def test(ipdb):
    global update
    update = 'keep IP test'
    save_iplist_as_db(ipdb, [])
    log('keeep IP 已保存完毕')
Example #6
0
def download_17mon_cniplist_as_db(ipdb):
    log('开始下载 17mon IP')
    iplist = download_cniplist(ipdb, parse_17mon_cniplist)
    save_iplist_as_db(ipdb, iplist)
    log('17mon IP 已保存完毕')
Example #7
0
def download_apnic_cniplist_as_db(ipdb):
    log('开始下载 APNIC IP')
    iplist = download_cniplist(ipdb, parse_apnic_cniplist)
    save_iplist_as_db(ipdb, iplist)
    log('APNIC IP 已保存完毕')