summaryrefslogtreecommitdiff
path: root/util/get_cert.py
blob: 2bfb60c217eed660ab8b5026b0d20b0720ba1c81 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import time
from hyper import HTTP20Connection, HTTP11Connection
from util.thread_timeout import time_limited
from main import TIMEOUT, UN_CONNECTED, CONNECTED_HTTP1_1, CONNECTED_HTTP2_0, NOT_SUPPORT_FOR_HTTP2, \
    make_doh_request_body, CERTIFICATE_VERIFY_FAILED
import threading
from util.util_http import make_ssl_context
import ssl, socket, sys, csv
from hyper.http20.exceptions import ConnectionError
from concurrent.futures import ThreadPoolExecutor
import os

root_dir = sys.path[0]

# %Y-%m-%d %H:%M:%S
datetime_str = time.strftime('%y%m%d%H', time.localtime(time.time()))
save_dir = "./verify"
if not os.path.exists(save_dir):
    os.mkdir(save_dir)
save_file = os.path.join(root_dir, save_dir, f"{datetime_str}.csv")
# f_verify = csv.writer(open(f"./verify/{datetime_str}.csv", "w", newline=""))
f = open(save_file, "w", newline="")
f_verify = csv.writer(f)
# csv.writer(f_verify)

lock = threading.Lock()

body = make_doh_request_body()


@time_limited(TIMEOUT * 10)
def doh_verify(ip, port):
    # print(ip, port, host, path, method)
    verify_mode = ssl.CERT_OPTIONAL

    ctx_2_0 = make_ssl_context()
    ctx_2_0.set_alpn_protocols(['h2'])
    # ctx_2_0.verify_mode = ssl.CERT_NONE
    conn = HTTP20Connection(ip, port=port, ssl_context=ctx_2_0)
    conn_status = UN_CONNECTED
    try:
        conn.connect()
        conn_status = CONNECTED_HTTP2_0
        # print("成功建立HTTP2.0连接!")
    except (AssertionError, TimeoutError, FileNotFoundError, ConnectionResetError, ConnectionRefusedError, OSError,
            ssl.SSLCertVerificationError, ssl.SSLError,
            socket.timeout,
            ConnectionError,  # hyper error
            ) as e:
        if e.__str__().startswith(NOT_SUPPORT_FOR_HTTP2):  # 预期内的错误,继续尝试HTTP1.1
            # print("建立连接失败!服务端不支持HTTP2.0,继续尝试HTTP1.1")
            ...
        elif e.__str__().startswith(CERTIFICATE_VERIFY_FAILED):  # 证书导致的错误,将sslContext设置为CERT_NONE
            # print("证书原因导致连接建立失败,设置sslContext为CERT_NONE")
            ctx_2_0.verify_mode = ssl.CERT_NONE
            verify_mode = ssl.CERT_NONE
            conn = HTTP20Connection(ip, port=port, ssl_context=ctx_2_0)
            try:
                conn.connect()
                conn_status = CONNECTED_HTTP2_0
                # print("成功建立HTTP2.0连接!")
            except (
                    AssertionError, TimeoutError, FileNotFoundError, ConnectionResetError, ConnectionRefusedError,
                    OSError,
                    ssl.SSLCertVerificationError, ssl.SSLError,
                    socket.timeout,
                    ConnectionError,  # hyper error
            ) as e:
                # print("建立连接失败!服务端不支持HTTP2.0,继续尝试HTTP1.1")
                ...
        else:
            # print("建立连接失败!错误信息如下:", e)
            return False

    if conn_status == UN_CONNECTED:
        ctx_1_1 = make_ssl_context()
        ctx_1_1.verify_mode = verify_mode
        conn = HTTP11Connection(ip, port=port, ssl_context=ctx_1_1)
        try:
            conn.connect()
            conn_status = CONNECTED_HTTP1_1
            # print("成功建立HTTP1.1连接!")
        except (TimeoutError, ConnectionRefusedError, FileNotFoundError, ConnectionAbortedError,
                ssl.SSLCertVerificationError, ssl.SSLError,
                socket.timeout, OSError
                ) as e:  # 如使用HTTP1.1仍然无法建立连接,则放弃
            # print("建立连接失败!错误信息如下:", e)
            return False

    try:
        cert = conn._sock.getpeercert()
    except AttributeError:
        cert = None
    lock.acquire()
    try:
        f_verify.writerow([ip, cert.__str__()])
    except UnicodeEncodeError:
        print(ip, cert.__str__())
    lock.release()


def run_with_thread_pool(max_workers, data_group, fn):
    # print("Before ThreadPool!")
    with ThreadPoolExecutor(max_workers=max_workers, thread_name_prefix="") as threadPool:
        for data in data_group:
            threadPool.submit(fn, *data)


if __name__ == '__main__':
    data_group = []
    with open("./suspect/no_cert_ips.csv") as fp:
        csv_reader = csv.reader(fp)
        for row in csv_reader:
            ip = row[0]
            data_group.append((ip, 443))
    print(len(data_group))
    run_with_thread_pool(64, data_group, doh_verify)
    f.close()