// ==UserScript== // @name 阻止视频网站利用WebRTC进行PCDN分发 // @version 1.4 // @description 阻止视频网站通过WebRTC将用户作为PCDN节点,并在尝试连接时弹出红色警告。增加了“不再提示”勾选功能。 // @author 嘉友友 // @icon data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSIjZGMxNDJjIiBkPSJNNTAgNSBDOTAgMjAgOTAgNDUgOTAgNDUgQzkwIDcwIDUwIDk1IDUwIDk1IEM1MCA5NSAxMCA3MCAxMCA0NSBDMTAgNDUgMTAgMjAgNTAgNSBaIi8+PHJlY3QgeD0iNDciIHk9IjMwIiB3aWR0aD0iNiIgaGVpZ2h0PSIyNSIgZmlsbD0iI2ZmZiIgcng9IjEiLz48Y2lyY2xlIGN4PSI1MCIgY3k9IjY4IiByPSI0IiBmaWxsPSIjZmZmIi8+PC9zdmc+ // @match *://*.iqiyi.com/* // @match *://*.v.qq.com/* // @match *://*.youku.com/* // @match *://*.bilibili.com/* // @match *://*.mgtv.com/* // @match *://*.tv.sohu.com/* // @match *://*.acfun.cn/* // @match *://*.migu.cn/* // @match *://*.cctv.com/* // @match *://*.cntv.cn/* // @match *://*.douyin.com/* // @match *://*.ixigua.com/* // @match *://*.pptv.com/* // @match *://*.wasu.cn/* // @match *://*.netflix.com/* // @match *://*.youtube.com/* // @match *://*.huya.com/* // @match *://*.kuaishou.com/* // @match *://*.xiaohongshu.com/* // @match *://*.douyu.com/* // @match *://*.tv.cctv.com/* // @match *://*.tiktok.com/* // @match *://*.twitch.tv/* // @match *://*.vimeo.com/* // @match *://*.disneyplus.com/* // @match *://*.primevideo.com/* // @match *://*.hulu.com/* // @grant none // @run-at document-start // @license GPL-3.0 // @namespace https://greasyfork.org/users/1336389 // @downloadURL https://update.greasyfork.icu/scripts/574129/%E9%98%BB%E6%AD%A2%E8%A7%86%E9%A2%91%E7%BD%91%E7%AB%99%E5%88%A9%E7%94%A8WebRTC%E8%BF%9B%E8%A1%8CPCDN%E5%88%86%E5%8F%91.user.js // @updateURL https://update.greasyfork.icu/scripts/574129/%E9%98%BB%E6%AD%A2%E8%A7%86%E9%A2%91%E7%BD%91%E7%AB%99%E5%88%A9%E7%94%A8WebRTC%E8%BF%9B%E8%A1%8CPCDN%E5%88%86%E5%8F%91.meta.js // ==/UserScript== (function() { 'use strict'; // --- 配置 --- const MAX_WARNINGS = 3; // 允许弹出的最大次数 let warningCount = 0; // 当前已弹出次数计数器 // --- 域名处理 --- function getIgnoredDomains() { try { return JSON.parse(localStorage.getItem('webrtc_block_ignored_domains') || '[]'); } catch (e) { return []; } } function isDomainIgnored() { const domains = getIgnoredDomains(); const hostname = window.location.hostname; // 检查是否在忽略列表中 return domains.some(d => hostname === d || hostname.endsWith('.' + d)); } function ignoreCurrentDomain() { let hostname = window.location.hostname; // 存储时自动去除前缀 if (hostname.startsWith('www.')) { hostname = hostname.substring(4); } const domains = getIgnoredDomains(); if (!domains.includes(hostname)) { domains.push(hostname); localStorage.setItem('webrtc_block_ignored_domains', JSON.stringify(domains)); console.log(`[Anti-PCDN] 已将 ${hostname} 加入不再提示列表。`); } } // --- 警告通知函数 --- function showBlockNotification() { // 防止重复弹出 if (document.getElementById('webrtc-block-warning')) return; // 检查 body 是否存在 if (!document.body) { return setTimeout(showBlockNotification, 100); } const div = document.createElement('div'); div.id = 'webrtc-block-warning'; // 样式:居中显示,红色醒目 div.style.position = 'fixed'; div.style.top = '50%'; div.style.left = '50%'; div.style.transform = 'translate(-50%, -50%)'; div.style.zIndex = '2147483647'; div.style.padding = '20px 30px'; div.style.background = 'rgba(220, 20, 60, 0.95)'; div.style.color = 'white'; div.style.fontFamily = 'Microsoft YaHei, Arial, sans-serif'; div.style.fontSize = '16px'; div.style.borderRadius = '8px'; div.style.boxShadow = '0 4px 20px rgba(0,0,0,0.6)'; div.style.cursor = 'pointer'; div.style.textAlign = 'center'; div.style.maxWidth = '80%'; div.style.wordBreak = 'break-all'; // 复选框 div.innerHTML = `
🛡️
⚠️ 已拦截 WebRTC 盗用
网站尝试利用您的带宽进行 PCDN 分发,已被阻止。
点击此处关闭
`; // 点击处理逻辑 div.onclick = function(e) { // 如果点击的是复选框,不关闭弹窗,只允许用户勾选 if (e.target && e.target.id === 'webrtc-never-ask') { return; } // 点击背景关闭时,检查是否勾选了"不再提示" const checkbox = document.getElementById('webrtc-never-ask'); if (checkbox && checkbox.checked) { ignoreCurrentDomain(); } div.remove(); }; document.body.appendChild(div); // 8秒后自动消失 setTimeout(() => { if (div && div.parentNode) { // 即使是自动关闭,如果之前勾选了选项,也要保存 const checkbox = document.getElementById('webrtc-never-ask'); if (checkbox && checkbox.checked) { ignoreCurrentDomain(); } div.remove(); } }, 8000); console.warn(`[Anti-PCDN] WebRTC 连接尝试已被拦截。(当前第 ${warningCount} 次提醒)`); } // --- 核心拦截逻辑 --- // 通用拦截处理函数 function handleWebRTCAttempt() { // 新增: 检查该网站是否已被设置为不再提示 if (isDomainIgnored()) { return; } // 次数限制逻辑 if (warningCount < MAX_WARNINGS) { showBlockNotification(); warningCount++; } else { // 超过次数后,仅在控制台输出 console.log('[Anti-PCDN] 网站仍在尝试连接,但已跳过弹窗提醒。'); } } // 创建一个虚假的 RTCPeerConnection 实例 function createDummyPeerConnection() { return { close: function() {}, createOffer: function() { return Promise.resolve(); }, createAnswer: function() { return Promise.resolve(); }, setLocalDescription: function() { return Promise.resolve(); }, setRemoteDescription: function() { return Promise.resolve(); }, addIceCandidate: function() { return Promise.resolve(); }, onicecandidate: null, ontrack: null, onconnectionstatechange: null, getStats: function() { return Promise.resolve(new Map()); } }; } // 拦截标准的 RTCPeerConnection (Chrome, Firefox, Edge) if (window.RTCPeerConnection) { window.RTCPeerConnection = function(...args) { handleWebRTCAttempt(); return createDummyPeerConnection(); }; } // 拦截 webkitRTCPeerConnection (Safari 旧版兼容) if (window.webkitRTCPeerConnection) { window.webkitRTCPeerConnection = function(...args) { handleWebRTCAttempt(); return createDummyPeerConnection(); }; } console.log('[Anti-PCDN] WebRTC 防护已启动'); })();