Ejemplo n.º 1
0
def handle_syn_ack(syn_ack):
    uncertain_ip = socket.inet_ntoa(syn_ack.src)
    if uncertain_ip in pending_syn:
        del pending_syn[uncertain_ip]
    expected_ttl = syn_ack_ttl.get((uncertain_ip, syn_ack.tcp.sport)) or 0
    if expected_ttl and abs(syn_ack.ttl - expected_ttl) > 2:
        record_jamming_event(uncertain_ip, 'tcp syn ack spoofing')
        LOGGER.error(
            'received spoofed SYN ACK: expected ttl is %s, actually is %s, the packet %s' %
            (expected_ttl, syn_ack.ttl, format_ip_packet(syn_ack)))
    syn_ack_ttl[(uncertain_ip, syn_ack.tcp.sport)] = syn_ack.ttl # later one should be the correct one as GFW is closer to us
    if uncertain_ip in international_zone:
        inject_poison_ack_to_fill_gfw_buffer_with_garbage(syn_ack, international_zone[uncertain_ip])
        return True
    elif uncertain_ip in domestic_zone:
        return True
    elif pending_connection.is_ip_pending(uncertain_ip):
        pending_connection.record_syn_ack(syn_ack)
        timeouted = pending_connection.is_ip_timeouted(uncertain_ip)
        if timeouted:
            international_ip = uncertain_ip
            LOGGER.info('treat ip as international due to timeout: %s' % international_ip)
            add_international_ip(international_ip, DEFAULT_TTL_TO_GFW)
        return False
    elif china_ip.is_china_ip(uncertain_ip):
        domestic_ip = uncertain_ip
        LOGGER.info('found domestic ip: %s' % domestic_ip)
        domestic_zone.add(domestic_ip)
        return True
    else:
        pending_connection.record_syn_ack(syn_ack)
        inject_ping_requests_to_find_right_ttl(uncertain_ip)
        return False
Ejemplo n.º 2
0
def handle_time_exceeded(ip_packet):
    time_exceed = ip_packet.icmp.data
    if not isinstance(time_exceed.data, dpkt.ip.IP):
        return
    te_ip_packet = time_exceed.data
    if not isinstance(te_ip_packet.data, dpkt.icmp.ICMP):
        return
    te_icmp_packet = te_ip_packet.data
    if not isinstance(te_icmp_packet.data, dpkt.icmp.ICMP.Echo):
        return
    te_icmp_echo = te_icmp_packet.data
    ttl = te_icmp_echo.id
    dst_ip = socket.inet_ntoa(te_ip_packet.dst)
    router_ip = socket.inet_ntoa(ip_packet.src)
    is_china_router = china_ip.is_china_ip(router_ip)
    if is_china_router and MAX_TTL_TO_GFW == ttl:
        LOGGER.info('treat ip as domestic as max ttl is still in china: %s' % dst_ip)
        add_domestic_ip(dst_ip)
        return
    elif not is_china_router and MIN_TTL_TO_GFW == ttl:
        LOGGER.info('treat ip as international as min ttl is not in china: %s' % dst_ip)
        add_international_ip(dst_ip, MAX_TTL_TO_GFW)
        return
    else:
        pending_connection.record_router(dst_ip, ttl, is_china_router)
        ttl_to_gfw = pending_connection.get_ttl_to_gfw(dst_ip)
        if ttl_to_gfw:
            LOGGER.info('found ttl to gfw: %s %s' % (dst_ip, ttl_to_gfw))
            add_international_ip(dst_ip, ttl_to_gfw)
Ejemplo n.º 3
0
def handle_time_exceeded(ip_packet):
    time_exceed = ip_packet.icmp.data
    if not isinstance(time_exceed.data, dpkt.ip.IP):
        return
    te_ip_packet = time_exceed.data
    if not isinstance(te_ip_packet.data, dpkt.icmp.ICMP):
        return
    te_icmp_packet = te_ip_packet.data
    if not isinstance(te_icmp_packet.data, dpkt.icmp.ICMP.Echo):
        return
    te_icmp_echo = te_icmp_packet.data
    ttl = te_icmp_echo.id
    dst_ip = socket.inet_ntoa(te_ip_packet.dst)
    router_ip = socket.inet_ntoa(ip_packet.src)
    is_china_router = china_ip.is_china_ip(router_ip)
    if is_china_router and MAX_TTL_TO_GFW == ttl:
        LOGGER.info(
            'treat ip as domestic as max ttl is still in china: %s, %s' %
            (dst_ip, pending_connection.get_detected_routers(dst_ip)))
        add_domestic_ip(dst_ip)
        return
    else:
        pending_connection.record_router(dst_ip, ttl, is_china_router)
        ttl_to_gfw = pending_connection.get_ttl_to_gfw(dst_ip)
        if ttl_to_gfw:
            LOGGER.info('found ttl to gfw: %s %s' %
                        (dst_ip, ttl_to_gfw - SAFETY_DELTA))
            add_international_ip(dst_ip, ttl_to_gfw - SAFETY_DELTA)
Ejemplo n.º 4
0
def pick_proxy_and_forward(client):
    if CHINA_PROXY and china_ip.is_china_ip(client.dst_ip):
        try:
            CHINA_PROXY.forward(client)
        except ProxyFallBack:
            pass
        return
    for i in range(3):
        proxy = pick_proxy(client)
        while proxy:
            if not client.host:
                break
            elif 'PUBLIC' in proxy.flags and any(fnmatch.fnmatch(client.host, host) for host in NO_PUBLIC_PROXY_HOSTS):
                client.tried_proxies.append(proxy)
            else:
                break
            proxy = pick_proxy(client)
        proxy = proxy or DIRECT_PROXY
        client.tried_proxies.append(proxy)
        if LOGGER.isEnabledFor(logging.DEBUG):
            LOGGER.debug('[%s] picked proxy: %s' % (repr(client), repr(proxy)))
        try:
            proxy.forward(client)
            return
        except ProxyFallBack, e:
            LOGGER.error('[%s] fall back to other proxy due to %s: %s' % (repr(client), e.reason, repr(proxy)))
        except NotHttp:
            continue
Ejemplo n.º 5
0
def handle_time_exceeded(ip_packet):
    global MAX_TTL_TO_GFW
    global MIN_TTL_TO_GFW
    global RANGE_OF_TTL_TO_GFW
    time_exceed = ip_packet.icmp.data
    if not isinstance(time_exceed.data, dpkt.ip.IP):
        return
    te_ip_packet = time_exceed.data
    if not isinstance(te_ip_packet.data, dpkt.icmp.ICMP):
        return
    te_icmp_packet = te_ip_packet.data
    if not isinstance(te_icmp_packet.data, dpkt.icmp.ICMP.Echo):
        return
    te_icmp_echo = te_icmp_packet.data
    ttl = te_icmp_echo.id
    dst_ip = socket.inet_ntoa(te_ip_packet.dst)
    router_ip = socket.inet_ntoa(ip_packet.src)
    is_china_router = china_ip.is_china_ip(router_ip)
    if is_china_router and MAX_TTL_TO_GFW == ttl:
        LOGGER.info('treat ip as domestic as max ttl is still in china: %s, %s' %
                    (dst_ip, pending_connection.get_detected_routers(dst_ip)))
        add_domestic_ip(dst_ip)
        return
    else:
        pending_connection.record_router(dst_ip, ttl, is_china_router)
        ttl_to_gfw = pending_connection.get_ttl_to_gfw(dst_ip)
        if ttl_to_gfw:
            LOGGER.info('found ttl to gfw: %s %s' % (dst_ip, ttl_to_gfw - SAFETY_DELTA))
            if ttl_to_gfw == MAX_TTL_TO_GFW:
                MIN_TTL_TO_GFW += 2
                MAX_TTL_TO_GFW += 2
                LOGGER.info('slide ttl range to [%s ~ %s]' % (MIN_TTL_TO_GFW, MAX_TTL_TO_GFW))
                RANGE_OF_TTL_TO_GFW = range(MIN_TTL_TO_GFW, MAX_TTL_TO_GFW + 1)
            add_international_ip(dst_ip, ttl_to_gfw - SAFETY_DELTA)
Ejemplo n.º 6
0
def add_to_white_list(ip):
    if ip not in white_list and not china_ip.is_china_ip(ip):
        if ip in black_list:
            LOGGER.info('add white list ip from black list: %s' % ip)
            black_list.remove(ip)
        else:
            LOGGER.info('add white list ip: %s' % ip)
        white_list.add(ip)
    pending_list.pop(ip, None)
Ejemplo n.º 7
0
def add_to_white_list(ip):
    if ip not in white_list and not china_ip.is_china_ip(ip):
        if ip in black_list:
            LOGGER.info('add white list ip from black list: %s' % ip)
            black_list.remove(ip)
        else:
            LOGGER.info('add white list ip: %s' % ip)
        white_list.add(ip)
    pending_list.pop(ip, None)
Ejemplo n.º 8
0
def handle_packet(nfqueue_element):
    try:
        ip_packet = dpkt.ip.IP(nfqueue_element.get_payload())
        ip = socket.inet_ntoa(ip_packet.dst)
        if china_ip.is_china_ip(ip):
            nfqueue_element.accept()
        elif ip in white_list:
            nfqueue_element.accept()
        elif ip in black_list:
            set_verdict_proxy(nfqueue_element, ip_packet)
        else:
            nfqueue_element.accept()
    except:
        LOGGER.exception('failed to handle packet')
        nfqueue_element.accept()
Ejemplo n.º 9
0
def handle_packet(nfqueue_element):
    try:
        ip_packet = dpkt.ip.IP(nfqueue_element.get_payload())
        ip = socket.inet_ntoa(ip_packet.dst)
        if china_ip.is_china_ip(ip):
            nfqueue_element.accept()
        elif ip in white_list:
            nfqueue_element.accept()
        elif ip in black_list:
            set_verdict_proxy(nfqueue_element, ip_packet)
        else:
            nfqueue_element.accept()
    except:
        LOGGER.exception('failed to handle packet')
        nfqueue_element.accept()
Ejemplo n.º 10
0
def handle_syn_ack(syn_ack):
    uncertain_ip = socket.inet_ntoa(syn_ack.src)
    full_proxy_service.add_to_white_list(uncertain_ip)
    if uncertain_ip in pending_syn:
        del pending_syn[uncertain_ip]
    expected_ttl = syn_ack_ttl.get((uncertain_ip, syn_ack.tcp.sport)) or 0
    if expected_ttl and abs(syn_ack.ttl - expected_ttl) > 2:
        log_jamming_event(uncertain_ip, 'tcp syn ack spoofing')
        LOGGER.error(
            'received spoofed SYN ACK: expected ttl is %s, actually is %s, the packet %s'
            % (expected_ttl, syn_ack.ttl, format_ip_packet(syn_ack)))
    syn_ack_ttl[(
        uncertain_ip, syn_ack.tcp.sport
    )] = syn_ack.ttl  # later one should be the correct one as GFW is closer to us
    if uncertain_ip in international_zone:
        inject_poison_ack_to_fill_gfw_buffer_with_garbage(
            syn_ack, international_zone[uncertain_ip])
        return True
    elif uncertain_ip in domestic_zone:
        return True
    elif pending_connection.is_ip_pending(uncertain_ip):
        pending_connection.record_syn_ack(syn_ack)
        timeouted = pending_connection.is_ip_timeouted(uncertain_ip)
        if timeouted:
            international_ip = uncertain_ip
            LOGGER.info(
                'treat ip as international due to timeout: %s, %s' %
                (international_ip,
                 pending_connection.get_detected_routers(international_ip)))
            ttl_to_gfw = pending_connection.get_ttl_to_gfw(
                international_ip, exact_match_only=False)
            add_international_ip(international_ip,
                                 (ttl_to_gfw or DEFAULT_TTL_TO_GFW) -
                                 SAFETY_DELTA)
        return False
    elif china_ip.is_china_ip(uncertain_ip):
        domestic_ip = uncertain_ip
        LOGGER.info('found domestic ip: %s' % domestic_ip)
        domestic_zone.add(domestic_ip)
        return True
    else:
        pending_connection.record_syn_ack(syn_ack)
        inject_ping_requests_to_find_right_ttl(uncertain_ip)
        return False
Ejemplo n.º 11
0
def pick_proxy_and_forward(client):
    if lan_ip.is_lan_traffic(client.src_ip, client.dst_ip):
        try:
            DIRECT_PROXY.forward(client)
        except ProxyFallBack:
            pass
        return
    if client.dst_ip in fqdns.BUILTIN_WRONG_ANSWERS():
        LOGGER.error('[%s] destination is GFW wrong answer' % repr(client))
        NONE_PROXY.forward(client)
        return
    if CHINA_PROXY and china_ip.is_china_ip(client.dst_ip):
        try:
            CHINA_PROXY.forward(client)
        except ProxyFallBack:
            pass
        return
    for i in range(3):
        proxy = pick_proxy(client)
        while proxy:
            if not client.host:
                break
            elif 'PUBLIC' in proxy.flags and any(fnmatch.fnmatch(client.host, host) for host in NO_PUBLIC_PROXY_HOSTS):
                client.tried_proxies[proxy] = 'skip PUBLIC'
            else:
                break
            proxy = pick_proxy(client)
        proxy = proxy or DIRECT_PROXY
        if is_direct_access_disabled() and isinstance(proxy, DirectProxy): # try disabled
            LOGGER.info('[%s] no proxy available, and DIRECT has been disabled' % repr(client))
            return
        if 'DIRECT' in proxy.flags:
            LOGGER.debug('[%s] picked proxy: %s' % (repr(client), repr(proxy)))
        else:
            LOGGER.info('[%s] picked proxy: %s' % (repr(client), repr(proxy)))
        try:
            proxy.forward(client)
            return
        except ProxyFallBack, e:
            LOGGER.error('[%s] fall back to other proxy due to %s: %s' % (repr(client), e.reason, repr(proxy)))
            client.tried_proxies[proxy] = e.reason
        except NotHttp:
            client.tried_proxies[proxy] = 'not http'
            continue
Ejemplo n.º 12
0
def handle_packet(nfqueue_element):
    try:
        if 0xcafe == nfqueue_element.get_mark():
            nfqueue_element.accept()
            return
        ip_packet = dpkt.ip.IP(nfqueue_element.get_payload())
        if ip_packet.tcp.dport not in {80, 443}:
            nfqueue_element.accept()
            return
        if lan_ip.is_lan_traffic(ip_packet):
            nfqueue_element.accept()
            return
        ip = socket.inet_ntoa(ip_packet.dst)
        if china_ip.is_china_ip(ip):
            nfqueue_element.accept()
        elif ip in black_list:
            set_verdict_proxy(nfqueue_element, ip_packet)
        elif ip in white_list:
            nfqueue_element.accept()
        else:
            nfqueue_element.accept()
    except:
        LOGGER.exception('failed to handle packet')
        nfqueue_element.accept()
Ejemplo n.º 13
0
 def match_dst(self, src, dst):
     matched = china_ip.is_china_ip(dst)
     if matched:
         LOGGER.info(self.matched_dst % dst)
     return matched
Ejemplo n.º 14
0
 def match_src(self, src, dst):
     matched = china_ip.is_china_ip(src)
     if matched:
         LOGGER.debug(self.matched_src % src)
     return matched
Ejemplo n.º 15
0
 def match_dst(self, src, dst):
     matched = china_ip.is_china_ip(dst)
     if matched:
         LOGGER.debug(self.matched_dst % dst)
     return matched
Ejemplo n.º 16
0
def add_to_white_list(ip):
    if ip not in white_list and not china_ip.is_china_ip(ip):
        LOGGER.info('add white list ip: %s' % ip)
        white_list.add(ip)
    pending_list.pop(ip, None)
Ejemplo n.º 17
0
 def match_src(self, src, dst):
     matched = china_ip.is_china_ip(src)
     if matched:
         LOGGER.info(self.matched_src % src)
     return matched