-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbackground.js
More file actions
341 lines (309 loc) · 14.4 KB
/
Copy pathbackground.js
File metadata and controls
341 lines (309 loc) · 14.4 KB
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
/**
* background.js — v5.2
* 指紋瀏覽器後台:全站 UA 偽裝、WebRTC 保護、帳號指紋持久化
*
* ===== v4.1 修改項目 =====
* [FIX] 只保留 iOS Safari UA(移除 CriOS),因為 Orion 是 WebKit 引擎,
* 偽裝成 Safari 的 TLS/HTTP2 指紋最接近,不會暴露
* [FIX] webRequest 優先使用 browser.webRequest(Orion 支援的命名空間)
* [FIX] Sec-CH-UA 系列 header 清除更完整
* [NEW] 新增 getActiveUA / copyUAForOrion 訊息支援
* [NEW] Accept header 偽裝(Safari 格式)
*/
// ===== User-Agent 列表 (iPhone Safari / Chrome) =====
const UA_LIST = [
// iOS 18.x Safari (新版 Version/26.x)
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.3.1 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.3 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2.1 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.4 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.1 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.3.2 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_6_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2.5 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.1.1 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.3.5 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.3.8 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2.9 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.1.8 Mobile/15E148 Safari/604.1",
// iOS 18.x Safari (舊版 Version/18.x)
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.1 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.4 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.7 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.2.1 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6.1 Mobile/15E148 Safari/604.1",
// iOS 18.x CriOS
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/131.0.6778.100 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/132.0.6834.90 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/133.0.6943.126 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/134.0.7000.110 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/135.0.7050.85 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/132.0.6834.77 Mobile/15E148 Safari/604.1",
// iOS 17.x Safari
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.7 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6.1 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.3 Mobile/15E148 Safari/604.1",
// iOS 17.x CriOS
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/120.0.6099.119 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/119.0.6045.169 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/118.0.5993.122 Mobile/15E148 Safari/604.1",
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1",
];
// ===== 全域 UA 狀態 =====
let activeUA = UA_LIST[0];
let activeOsVer = '18.7';
let uaSpoofEnabled = false; // UA 開關
let fpSpoofEnabled = false; // 指紋開關
// 從 storage 還原上次使用的 UA + 開關狀態
chrome.storage.local.get(['currentUA', 'osVer', 'uaSpoofEnabled', 'fpSpoofEnabled'], (data) => {
if (data.currentUA) activeUA = data.currentUA;
if (data.osVer) activeOsVer = data.osVer;
if (typeof data.uaSpoofEnabled === 'boolean') uaSpoofEnabled = data.uaSpoofEnabled;
if (typeof data.fpSpoofEnabled === 'boolean') fpSpoofEnabled = data.fpSpoofEnabled;
console.log('[UA] activeUA:', activeUA.substring(0, 60) + '... | UA:', uaSpoofEnabled, '| FP:', fpSpoofEnabled);
});
/**
* 套用 UA(儲存 + 嘗試 DNR + webRequest 會自動使用全域變數)
*/
async function applyUARules(selectedUA, osVer, updateTime = false) {
activeUA = selectedUA;
activeOsVer = osVer;
const storageData = { currentUA: selectedUA, osVer: osVer };
if (updateTime) storageData.uaUpdateTime = Date.now();
chrome.storage.local.set(storageData);
// 嘗試 DNR(Chromium 瀏覽器適用,Orion 會靜默失敗)
try {
if (chrome.declarativeNetRequest) {
const ALL_RESOURCE_TYPES = [
'main_frame', 'sub_frame', 'stylesheet', 'script', 'image',
'font', 'object', 'xmlhttprequest', 'ping', 'csp_report',
'media', 'websocket', 'other',
];
await chrome.declarativeNetRequest.updateDynamicRules({
removeRuleIds: [1, 2],
addRules: [
{
id: 1,
priority: 1,
action: {
type: 'modifyHeaders',
requestHeaders: [
{ header: 'User-Agent', operation: 'set', value: selectedUA },
{ header: 'Sec-CH-UA', operation: 'remove' },
{ header: 'Sec-CH-UA-Full-Version-List', operation: 'remove' },
{ header: 'Sec-CH-UA-Arch', operation: 'remove' },
{ header: 'Sec-CH-UA-Bitness', operation: 'remove' },
{ header: 'Sec-CH-UA-Model', operation: 'remove' },
{ header: 'Sec-CH-UA-WoW64', operation: 'remove' },
{ header: 'Sec-CH-UA-Mobile', operation: 'remove' },
{ header: 'Sec-CH-UA-Platform', operation: 'remove' },
{ header: 'Sec-CH-UA-Platform-Version', operation: 'remove' },
],
},
condition: {
urlFilter: '*',
resourceTypes: ALL_RESOURCE_TYPES,
},
},
],
});
console.log('[UA] DNR 規則已套用');
}
} catch (err) {
// Orion 不支援 DNR,靜默處理
}
}
/**
* 隨機選取新 UA 並套用
*/
async function updateUA() {
const selectedUA = UA_LIST[Math.floor(Math.random() * UA_LIST.length)];
const osMatch = selectedUA.match(/OS ([\d_]+)/);
const osVer = osMatch ? osMatch[1].replace(/_/g, '.') : '18.7';
await applyUARules(selectedUA, osVer, true);
return { ua: selectedUA, ver: osVer };
}
/**
* 從 storage 還原 UA
*/
function restoreUA() {
chrome.storage.local.get(['currentUA', 'osVer'], (data) => {
if (data.currentUA && data.osVer) {
applyUARules(data.currentUA, data.osVer, false);
} else {
updateUA();
}
});
}
/**
* WebRTC 保護
*/
function applyWebRTCPolicy() {
if (chrome.privacy && chrome.privacy.network) {
chrome.privacy.network.webRTCIPHandlingPolicy.set({
value: 'disable_non_proxied_udp',
});
}
}
// ===== 訊息監聽 =====
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'refreshUA') {
updateUA().then((result) => {
sendResponse(result);
}).catch((err) => {
sendResponse({ error: err.toString() });
});
return true;
}
if (message.action === 'applyUA') {
const { ua, ver } = message;
if (!ua || !ver) {
sendResponse({ error: 'missing ua or ver' });
return false;
}
applyUARules(ua, ver, true).then(() => {
sendResponse({ ua, ver });
}).catch((err) => {
sendResponse({ error: err.toString() });
});
return true;
}
if (message.action === 'getRandomUA') {
const selectedUA = UA_LIST[Math.floor(Math.random() * UA_LIST.length)];
const osMatch = selectedUA.match(/OS ([\d_]+)/);
const osVer = osMatch ? osMatch[1].replace(/_/g, '.') : '18.7';
sendResponse({ ua: selectedUA, ver: osVer });
return false;
}
// [v4.1] 取得當前活躍 UA
if (message.action === 'getActiveUA') {
sendResponse({ ua: activeUA, ver: activeOsVer, enabled: uaSpoofEnabled });
return false;
}
// [v4.1] UA 偽裝總開關
if (message.action === 'toggleUASpoof') {
uaSpoofEnabled = !!message.enabled;
chrome.storage.local.set({ uaSpoofEnabled });
console.log('[UA] 總開關:', uaSpoofEnabled ? '開啟' : '關閉');
sendResponse({ enabled: uaSpoofEnabled });
return false;
}
if (message.action === 'getUASpoofState') {
sendResponse({ enabled: uaSpoofEnabled });
return false;
}
// [v4.2] 指紋偽裝總開關
if (message.action === 'toggleFPSpoof') {
fpSpoofEnabled = !!message.enabled;
chrome.storage.local.set({ fpSpoofEnabled });
console.log('[FP] 指紋開關:', fpSpoofEnabled ? '開啟' : '關閉');
sendResponse({ enabled: fpSpoofEnabled });
return false;
}
if (message.action === 'getFPSpoofState') {
sendResponse({ enabled: fpSpoofEnabled });
return false;
}
// 取得指定 domain 的 cookies
if (message.action === 'getCookiesForDomains') {
const { domains } = message;
if (!domains || !Array.isArray(domains)) {
sendResponse({ cookies: [] });
return false;
}
const promises = domains.map(
(domain) => new Promise((resolve) => {
chrome.cookies.getAll({ domain }, (cookies) => resolve(cookies || []));
})
);
Promise.all(promises).then((results) => {
const seen = new Set();
const merged = results.flat().filter((c) => {
const key = c.domain + '|' + c.name + '|' + c.path;
if (seen.has(key)) return false;
seen.add(key);
return true;
});
sendResponse({ cookies: merged });
});
return true;
}
});
// ===== 事件監聽 =====
chrome.runtime.onInstalled.addListener(() => {
updateUA();
applyWebRTCPolicy();
});
chrome.runtime.onStartup.addListener(() => {
restoreUA();
applyWebRTCPolicy();
});
// ===== webRequest — HTTP Header UA 偽裝 =====
// 這是 MV2 最可靠的 HTTP header 修改方式
// 在 Orion 上可能不支援 blocking 模式,但我們仍然嘗試
(function initWebRequestUA() {
const webReq = (typeof browser !== 'undefined' && browser.webRequest)
? browser.webRequest
: (chrome.webRequest || null);
if (!webReq || !webReq.onBeforeSendHeaders) {
console.warn('[UA] webRequest API 不可用');
return;
}
const listener = (details) => {
if (!activeUA || !uaSpoofEnabled) return { requestHeaders: details.requestHeaders };
const headers = (details.requestHeaders || []).filter((h) => {
const name = h.name.toLowerCase();
// 移除所有 Sec-CH-UA 系列 + 不一致的 Accept header
return !name.startsWith('sec-ch-ua');
});
// 覆蓋 User-Agent
let uaFound = false;
for (const h of headers) {
if (h.name.toLowerCase() === 'user-agent') {
h.value = activeUA;
uaFound = true;
break;
}
}
if (!uaFound) {
headers.push({ name: 'User-Agent', value: activeUA });
}
// 覆蓋 Accept header 為 Safari 格式
for (const h of headers) {
if (h.name.toLowerCase() === 'accept') {
// 只在 main_frame / sub_frame 請求覆蓋
if (details.type === 'main_frame' || details.type === 'sub_frame') {
h.value = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
}
break;
}
}
return { requestHeaders: headers };
};
const filter = { urls: ['<all_urls>'] };
// 依序嘗試不同的 extraInfoSpec
const specOptions = [
['blocking', 'requestHeaders', 'extraHeaders'],
['blocking', 'requestHeaders'],
];
let registered = false;
for (const spec of specOptions) {
try {
webReq.onBeforeSendHeaders.addListener(listener, filter, spec);
console.log('[UA] webRequest 已啟用,spec:', spec.join(', '));
registered = true;
break;
} catch (e) {
// 嘗試下一個 spec
}
}
if (!registered) {
console.warn('[UA] webRequest 所有模式都註冊失敗(Orion 可能不支援 blocking)');
}
})();