Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
grasscutters
GitHub Repository: grasscutters/grasscutter
Path: blob/development/scripts/proxy.py
3153 views
1
##
2
#
3
# Copyright (C) 2002-2022 MlgmXyysd All Rights Reserved.
4
#
5
##
6
7
##
8
#
9
# Animation Company script for mitmproxy
10
#
11
# https://github.com/MlgmXyysd/
12
#
13
# *Original fiddler script from https://github.lunatic.moe/fiddlerscript
14
#
15
# Environment requirement:
16
# - mitmdump from mitmproxy
17
#
18
# @author MlgmXyysd
19
# @version 1.1
20
#
21
##
22
23
import collections
24
import random
25
from mitmproxy import http, connection, ctx, tls
26
from abc import ABC, abstractmethod
27
from enum import Enum
28
from mitmproxy.utils import human
29
from proxy_config import USE_SSL
30
from proxy_config import REMOTE_HOST
31
from proxy_config import REMOTE_PORT
32
33
class MlgmXyysd_Animation_Company_Proxy:
34
35
LIST_DOMAINS = [
36
"api-os-takumi.mihoyo.com",
37
"hk4e-api-os-static.mihoyo.com",
38
"hk4e-sdk-os.mihoyo.com",
39
"dispatchosglobal.yuanshen.com",
40
"osusadispatch.yuanshen.com",
41
"account.mihoyo.com",
42
"log-upload-os.mihoyo.com",
43
"dispatchcntest.yuanshen.com",
44
"devlog-upload.mihoyo.com",
45
"webstatic.mihoyo.com",
46
"log-upload.mihoyo.com",
47
"hk4e-sdk.mihoyo.com",
48
"api-beta-sdk.mihoyo.com",
49
"api-beta-sdk-os.mihoyo.com",
50
"cnbeta01dispatch.yuanshen.com",
51
"dispatchcnglobal.yuanshen.com",
52
"cnbeta02dispatch.yuanshen.com",
53
"sdk-os-static.mihoyo.com",
54
"webstatic-sea.mihoyo.com",
55
"webstatic-sea.hoyoverse.com",
56
"hk4e-sdk-os-static.hoyoverse.com",
57
"sdk-os-static.hoyoverse.com",
58
"api-account-os.hoyoverse.com",
59
"hk4e-sdk-os.hoyoverse.com",
60
"overseauspider.yuanshen.com",
61
"gameapi-account.mihoyo.com",
62
"minor-api.mihoyo.com",
63
"public-data-api.mihoyo.com",
64
"uspider.yuanshen.com",
65
"sdk-static.mihoyo.com",
66
"abtest-api-data-sg.hoyoverse.com",
67
"log-upload-os.hoyoverse.com"
68
]
69
70
def request(self, flow: http.HTTPFlow) -> None:
71
if flow.request.pretty_host in self.LIST_DOMAINS:
72
if USE_SSL:
73
flow.request.scheme = "https"
74
else:
75
flow.request.scheme = "http"
76
flow.request.host = REMOTE_HOST
77
flow.request.port = REMOTE_PORT
78
79
class InterceptionResult(Enum):
80
SUCCESS = 1
81
FAILURE = 2
82
SKIPPED = 3
83
84
85
class TlsStrategy(ABC):
86
def __init__(self):
87
self.history = collections.defaultdict(lambda: collections.deque(maxlen=200))
88
89
@abstractmethod
90
def should_intercept(self, server_address: connection.Address) -> bool:
91
raise NotImplementedError()
92
93
def record_success(self, server_address):
94
self.history[server_address].append(InterceptionResult.SUCCESS)
95
96
def record_failure(self, server_address):
97
self.history[server_address].append(InterceptionResult.FAILURE)
98
99
def record_skipped(self, server_address):
100
self.history[server_address].append(InterceptionResult.SKIPPED)
101
102
103
class ConservativeStrategy(TlsStrategy):
104
def should_intercept(self, server_address: connection.Address) -> bool:
105
return InterceptionResult.FAILURE not in self.history[server_address]
106
107
108
class ProbabilisticStrategy(TlsStrategy):
109
def __init__(self, p: float):
110
self.p = p
111
super().__init__()
112
113
def should_intercept(self, server_address: connection.Address) -> bool:
114
return random.uniform(0, 1) < self.p
115
116
117
class MaybeTls:
118
strategy: TlsStrategy
119
120
def load(self, l):
121
l.add_option(
122
"tls_strategy", int, 0,
123
"TLS passthrough strategy. If set to 0, connections will be passed through after the first unsuccessful "
124
"handshake. If set to 0 < p <= 100, connections with be passed through with probability p.",
125
)
126
127
def configure(self, updated):
128
if "tls_strategy" not in updated:
129
return
130
if ctx.options.tls_strategy > 0:
131
self.strategy = ProbabilisticStrategy(ctx.options.tls_strategy / 100)
132
else:
133
self.strategy = ConservativeStrategy()
134
135
def tls_clienthello(self, data: tls.ClientHelloData):
136
server_address = data.context.server.peername
137
if not self.strategy.should_intercept(server_address):
138
ctx.log(f"TLS passthrough: {human.format_address(server_address)}.")
139
data.ignore_connection = True
140
self.strategy.record_skipped(server_address)
141
142
def tls_established_client(self, data: tls.TlsData):
143
server_address = data.context.server.peername
144
ctx.log(f"TLS handshake successful: {human.format_address(server_address)}")
145
self.strategy.record_success(server_address)
146
147
def tls_failed_client(self, data: tls.TlsData):
148
server_address = data.context.server.peername
149
ctx.log(f"TLS handshake failed: {human.format_address(server_address)}")
150
self.strategy.record_failure(server_address)
151
152
addons = [
153
MlgmXyysd_Animation_Company_Proxy(),
154
MaybeTls()
155
]
156
157