├── res ├── icon_32.png ├── icon_128.png ├── screenshot.png ├── random_ip.js ├── background.js ├── popup.js └── random_ua.js ├── _locales ├── zh_CN │ └── messages.json └── en_US │ └── messages.json ├── manifest.json ├── README.md └── popup.html /res/icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aTool-org/header-customize/HEAD/res/icon_32.png -------------------------------------------------------------------------------- /res/icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aTool-org/header-customize/HEAD/res/icon_128.png -------------------------------------------------------------------------------- /res/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aTool-org/header-customize/HEAD/res/screenshot.png -------------------------------------------------------------------------------- /_locales/zh_CN/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extDesp": { 3 | "message": "一个可以自定义HTTP Header信息的Chrome插件,包括Referer访问来源、随机UA信息、随机IP地址。" 4 | }, 5 | "extName": { 6 | "message": "Header自定义工具" 7 | }, 8 | "refererSwitchOn": { 9 | "message": "开启自定义Referer" 10 | }, 11 | "writeCusReferer": { 12 | "message": "填写Referrer访问来源" 13 | }, 14 | "randomUASwitchOn": { 15 | "message": "开启随机UA" 16 | }, 17 | "randomIPSwitchOn": { 18 | "message": "开启随机IP地址" 19 | }, 20 | "waiting": { 21 | "message": "请稍等…" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /_locales/en_US/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extDesp": { 3 | "message": "Can Customize HTTP Header, Include Referer / Ramdom UA / Random IP." 4 | }, 5 | "extName": { 6 | "message": "HTTP Header Modifier" 7 | }, 8 | "refererSwitchOn": { 9 | "message": "Customized ON / OFF" 10 | }, 11 | "writeCusReferer": { 12 | "message": "Write Customized Referer" 13 | }, 14 | "randomUASwitchOn": { 15 | "message": "Random UA ON / OFF" 16 | }, 17 | "randomIPSwitchOn": { 18 | "message": "Random IP ON / OFF" 19 | }, 20 | "waiting": { 21 | "message": "Please wait..." 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "browser_action": { 3 | "default_icon": "res/icon_32.png", 4 | "default_popup": "popup.html" 5 | }, 6 | "default_locale": "zh_CN", 7 | "description": "__MSG_extDesp__", 8 | "icons": { 9 | "128": "res/icon_128.png", 10 | "32": "res/icon_32.png" 11 | }, 12 | "manifest_version": 2, 13 | "name": "__MSG_extName__", 14 | "permissions": [ "webRequest", "webRequestBlocking", "", "storage" ], 15 | "version": "1.0.2", 16 | "background" : { 17 | "scripts": [ 18 | "res/chineseIp.js", 19 | "res/random_ip.js", 20 | "res/random_ua.js", 21 | "res/background.js" 22 | ] 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![header-customize](res/icon_128.png)](https://www.atool.org) 2 | 3 | ## [header-customize] 4 | 5 | 一个Chrome浏览器插件,用于自定义HTTP的header信息,用于保护referer、UA、IP等隐私信息。使用效果如下图所示: 6 | 7 | ![res/screenshot.png](res/screenshot.png) 8 | 9 | 意见反馈及主页: [http://www.atool.org/](http://www.atool.org/) 10 | 11 | ### 一、安装方法 12 | 13 | 1. Chrome插件商店下载地址:[https://chrome.google.com/webstore/detail/header%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B7%A5%E5%85%B7/maaccnhcoaehdeehahenkmchinbdjjmi](https://chrome.google.com/webstore/detail/header%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B7%A5%E5%85%B7/maaccnhcoaehdeehahenkmchinbdjjmi)。【推荐】 14 | 2. 自己下载本项目代码使用,拖入到浏览器中安装即可。 15 | 3. 备注:请勿自行分发。 16 | 17 | 18 | ### 二、目地背景 19 | 20 | 最开始做这个的原因是,www.atool.org最近有很来访问来源的其他网站来源,当时进去看的时候,却并没有什么链接,所以想到应该是修改referer的方式来伪造访问来源。 21 | 22 | 然后进一步想到,很多10元刷1w自然流量的广告,感觉他们的做法应该是大量刷referer,然后再网站流量统计中占有很高的排名,然后站长看到之后会因为好奇点到referer网站查看,从而形成自然流量。 23 | 24 | 1. 做一个自定义referer的插件,自己为自己刷自然流量 25 | 2. 伪造UA、伪造IP来隐藏自己的上网信息,同时提高referer的IP流量数 26 | 3. 学学chrome插件开发 27 | 28 | 29 | ### 三、后续工作 30 | 31 | 1. 更多的HTTP header配置; -------------------------------------------------------------------------------- /popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 37 | 38 | 39 | 40 | 41 |

1. Referer

42 | 43 | 44 |
45 |

2. UserAgent

46 | 47 |
48 |

3. IP Address

49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /res/random_ip.js: -------------------------------------------------------------------------------- 1 | function iptoLong(ip) { 2 | var ipl = 0; 3 | ip.split('.').forEach(function(octet) { 4 | ipl <<= 8; 5 | ipl += parseInt(octet); 6 | }); 7 | return(ipl >>> 0); 8 | }; 9 | 10 | function ipfromLong(ipl) { 11 | return ((ipl >>> 24) + '.' + 12 | (ipl >> 16 & 255) + '.' + 13 | (ipl >> 8 & 255) + '.' + 14 | (ipl & 255) ); 15 | }; 16 | 17 | //随机产生一个中国IP 18 | function getChineseIp(provinceArray){ 19 | var provinceArray=provinceArray||getProvinces(chineseIps); 20 | if(!(provinceArray instanceof Array)){ 21 | provinceArray=[provinceArray]; 22 | } 23 | var provinceName=getRandomItem(provinceArray); 24 | var ipAddress=getProvinceRandomIp(provinceName); 25 | return ipAddress; 26 | } 27 | 28 | 29 | //随机产生指定省的随机ip 30 | function getProvinceRandomIp(provinceName){ 31 | var ipAddress=null; 32 | if(chineseIps.hasOwnProperty(provinceName)){ 33 | provinceIps=chineseIps[provinceName]; 34 | var item=getRandomItem(provinceIps); 35 | ipAddress=getRandomIp(item.min,item.max); 36 | } 37 | return ipAddress; 38 | } 39 | 40 | //随机返回minIp到maxIp之间的ip,包括minIp和maxIp 41 | function getRandomIp(minIp, maxIp){ 42 | var min=iptoLong(minIp); 43 | var max=iptoLong(maxIp); 44 | var randomNum=getRandomNum(min,max+1); 45 | return ipfromLong(randomNum); 46 | } 47 | 48 | //获取中国各省市名称 49 | function getProvinces(chineseIps){ 50 | var provinces=[]; 51 | for(var province in chineseIps){ 52 | provinces.push(province); 53 | } 54 | return provinces; 55 | } 56 | 57 | //随机产生指定列表中的元素 58 | function getRandomItem(list){ 59 | var index=getRandomNum(0,list.length); 60 | return list[index]; 61 | } 62 | 63 | 64 | //随机返回min到max之间的整数,但不包括max 65 | function getRandomNum(min,max){ 66 | return Math.floor(Math.random()*(max-min)+min); 67 | } 68 | -------------------------------------------------------------------------------- /res/background.js: -------------------------------------------------------------------------------- 1 | var refererInjecting = false; //用户勾选的是否注入 2 | var referer = ""; //用户填写的refer 3 | // var refererHeader = { "name": "Referer", "value": "" }; //referer注入header信息 4 | 5 | var uaInjecting = false; 6 | var ipInjecting = false; 7 | 8 | 9 | // referer ============================ 10 | refererInjector = function (details) { 11 | details.requestHeaders.push({ "name": "Referer", "value": referer }); 12 | return { "requestHeaders": details.requestHeaders }; 13 | }, 14 | startRefererInjecting = function () { 15 | if(! refererInjecting) { 16 | chrome.webRequest.onBeforeSendHeaders.addListener(refererInjector, {urls: [""], types: ["main_frame"]}, ["blocking", "requestHeaders"]); 17 | refererInjecting = true; 18 | } 19 | }, 20 | stopRefererInjecting = function () { 21 | chrome.webRequest.onBeforeSendHeaders.removeListener(refererInjector); 22 | refererInjecting = false; 23 | }, 24 | 25 | 26 | // ua ============================ 27 | uaInjector = function (details) { 28 | details.requestHeaders.push({ "name": "User-Agent", "value": generateUA() }); 29 | return { "requestHeaders": details.requestHeaders }; 30 | }, 31 | startUAInjecting = function () { 32 | if(! uaInjecting) { 33 | chrome.webRequest.onBeforeSendHeaders.addListener(uaInjector, {urls: [""]}, ["blocking", "requestHeaders"]); 34 | uaInjecting = true; 35 | } 36 | }, 37 | stopUAInjecting = function () { 38 | chrome.webRequest.onBeforeSendHeaders.removeListener(uaInjector); 39 | uaInjecting = false; 40 | }, 41 | 42 | 43 | // ip ============================ 44 | ipInjector = function (details) { 45 | var IP = getChineseIp(); 46 | details.requestHeaders.push({ "name": "X-Forwarded-For", "value": IP }); 47 | details.requestHeaders.push({ "name": "X-Client-Ip", "value": IP }); 48 | return { "requestHeaders": details.requestHeaders }; 49 | }, 50 | startIPInjecting = function () { 51 | if(! ipInjecting) { 52 | console.log("add ip"); 53 | chrome.webRequest.onBeforeSendHeaders.addListener(ipInjector, {urls: [""]}, ["blocking", "requestHeaders"]); 54 | ipInjecting = true; 55 | } 56 | }, 57 | stopIPInjecting = function () { 58 | chrome.webRequest.onBeforeSendHeaders.removeListener(ipInjector); 59 | ipInjecting = false; 60 | }; -------------------------------------------------------------------------------- /res/popup.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('DOMContentLoaded', function() { 2 | var backgroundPage = chrome.extension.getBackgroundPage(); 3 | 4 | var refererSwitch = document.querySelector("#referer_switch"); //referer 开关 5 | var referer = document.querySelector("#referer"); //referer 输入框 6 | 7 | var uaRandomSwitch = document.querySelector("#random_ua"); // UA 随机 开关 8 | 9 | var ipRandomSwitch = document.querySelector("#random_ip"); // IP 随机 开关 10 | 11 | // 执行初始化 12 | initDOM(); 13 | // load config from storage 14 | function initDOM() { 15 | // load locale 16 | document.querySelector("#referer_text").innerHTML = chrome.i18n.getMessage("refererSwitchOn"); 17 | referer.setAttribute("placeholder", chrome.i18n.getMessage("writeCusReferer")); 18 | document.querySelector("#ua_text").innerHTML = chrome.i18n.getMessage("randomUASwitchOn"); 19 | document.querySelector("#ip_text").innerHTML = chrome.i18n.getMessage("randomIPSwitchOn"); 20 | 21 | chrome.storage.local.get(["referer", "refererInjecting", "randomUA", "randomIP"], function(data) { 22 | // refererInjecting 23 | if (data.refererInjecting) { 24 | refererSwitch.checked = true; 25 | referer.disabled = false; 26 | referer.style.color = "green"; 27 | referer.focus(); 28 | 29 | } 30 | else { 31 | referer.disabled = true; 32 | referer.style.color = "red"; 33 | } 34 | // referer 35 | if (data.referer) { 36 | referer.value = data.referer; 37 | backgroundPage.referer = data.referer; 38 | } 39 | 40 | // ua 41 | if (data.randomUA) { 42 | uaRandomSwitch.checked = true; 43 | // backgroundPage.uaInjecting = true; 44 | } 45 | else { 46 | uaRandomSwitch.checked = false; 47 | } 48 | 49 | // ip 50 | if (data.randomIP) { 51 | ipRandomSwitch.checked = true; 52 | // backgroundPage.ipInjecting = true; 53 | } 54 | else { 55 | ipRandomSwitch.checked = false; 56 | } 57 | // 开始注册后台任务 58 | registeBackground(); 59 | }); 60 | } 61 | 62 | function saveConfig(refererText, isRefererInjecting, isRandomUA, isRandomIP) { 63 | chrome.storage.local.set({ 64 | 'referer': refererText, 65 | "refererInjecting": isRefererInjecting, 66 | "randomUA": isRandomUA, 67 | "randomIP": isRandomIP 68 | }, function() { 69 | // do nothing 70 | }); 71 | } 72 | 73 | // Some Event 74 | function registeBackground() { 75 | // referer开关 76 | if (refererSwitch.checked) backgroundPage.startRefererInjecting(); 77 | 78 | refererSwitch.addEventListener("click", function(e) { 79 | saveConfig(referer.value, refererSwitch.checked, uaRandomSwitch.checked, ipRandomSwitch.checked); 80 | 81 | if (refererSwitch.checked) { 82 | referer.disabled = false; 83 | referer.style.color = "green"; 84 | backgroundPage.startRefererInjecting(); 85 | referer.focus(); 86 | } else { 87 | referer.disabled = true; 88 | referer.style.color = "red"; 89 | backgroundPage.stopRefererInjecting(); 90 | } 91 | }); 92 | // referer text 93 | referer.addEventListener("change", function(e) { 94 | saveConfig(referer.value, refererSwitch.checked, uaRandomSwitch.checked, ipRandomSwitch.checked); 95 | 96 | backgroundPage.referer = referer.value; 97 | if (refererSwitch.checked) { 98 | backgroundPage.startRefererInjecting(); 99 | } 100 | }); 101 | 102 | // ua开关 103 | if (uaRandomSwitch.checked) backgroundPage.startUAInjecting(); 104 | 105 | uaRandomSwitch.addEventListener("click", function(e) { 106 | saveConfig(referer.value, refererSwitch.checked, uaRandomSwitch.checked, ipRandomSwitch.checked); 107 | 108 | if (uaRandomSwitch.checked) { 109 | backgroundPage.startUAInjecting(); 110 | } else { 111 | backgroundPage.stopUAInjecting(); 112 | } 113 | }); 114 | 115 | // ip开关 116 | if (ipRandomSwitch.checked) backgroundPage.startIPInjecting(); 117 | 118 | ipRandomSwitch.addEventListener("click", function(e) { 119 | saveConfig(referer.value, refererSwitch.checked, uaRandomSwitch.checked, ipRandomSwitch.checked); 120 | if (ipRandomSwitch.checked) { 121 | backgroundPage.startIPInjecting(); 122 | } else { 123 | backgroundPage.stopIPInjecting(); 124 | } 125 | }); 126 | } 127 | }); -------------------------------------------------------------------------------- /res/random_ua.js: -------------------------------------------------------------------------------- 1 | function rnd(a, b) { 2 | //calling rnd() with no arguments is identical to rnd(0, 100) 3 | a = a || 0; 4 | b = b || 100; 5 | 6 | if (typeof b === 'number' && typeof a === 'number') { 7 | //rnd(int min, int max) returns integer between min, max 8 | return (function (min, max) { 9 | if (min > max) { 10 | throw new RangeError('expected min <= max; got min = ' + min + ', max = ' + max); 11 | } 12 | return Math.floor(Math.random() * (max - min + 1)) + min; 13 | }(a, b)); 14 | } 15 | 16 | if (Object.prototype.toString.call(a) === "[object Array]") { 17 | //returns a random element from array (a), even weighting 18 | return a[Math.floor(Math.random() * a.length)]; 19 | } 20 | 21 | if (a && typeof a === 'object') { 22 | //returns a random key from the passed object; keys are weighted by the decimal probability in their value 23 | return (function (obj) { 24 | var rand = rnd(0, 100) / 100, min = 0, max = 0, key, return_val; 25 | 26 | for (key in obj) { 27 | if (obj.hasOwnProperty(key)) { 28 | max = obj[key] + min; 29 | return_val = key; 30 | if (rand >= min && rand <= max) { 31 | break; 32 | } 33 | min = min + obj[key]; 34 | } 35 | } 36 | 37 | return return_val; 38 | }(a)); 39 | } 40 | 41 | throw new TypeError('Invalid arguments passed to rnd. (' + (b ? a + ', ' + b : a) + ')'); 42 | } 43 | 44 | function randomLang() { 45 | return rnd(['AB', 'AF', 'AN', 'AR', 'AS', 'AZ', 'BE', 'BG', 'BN', 'BO', 'BR', 'BS', 'CA', 'CE', 'CO', 'CS', 46 | 'CU', 'CY', 'DA', 'DE', 'EL', 'EN', 'EO', 'ES', 'ET', 'EU', 'FA', 'FI', 'FJ', 'FO', 'FR', 'FY', 47 | 'GA', 'GD', 'GL', 'GV', 'HE', 'HI', 'HR', 'HT', 'HU', 'HY', 'ID', 'IS', 'IT', 'JA', 'JV', 'KA', 48 | 'KG', 'KO', 'KU', 'KW', 'KY', 'LA', 'LB', 'LI', 'LN', 'LT', 'LV', 'MG', 'MK', 'MN', 'MO', 'MS', 49 | 'MT', 'MY', 'NB', 'NE', 'NL', 'NN', 'NO', 'OC', 'PL', 'PT', 'RM', 'RO', 'RU', 'SC', 'SE', 'SK', 50 | 'SL', 'SO', 'SQ', 'SR', 'SV', 'SW', 'TK', 'TR', 'TY', 'UK', 'UR', 'UZ', 'VI', 'VO', 'YI', 'ZH']); 51 | } 52 | 53 | function randomBrowserAndOS() { 54 | var browser = rnd({ 55 | chrome: .45132810566, 56 | iexplorer: .27477061836, 57 | firefox: .19384170608, 58 | safari: .06186781118, 59 | opera: .01574236955 60 | }), 61 | os = { 62 | chrome: {win: .89, mac: .09 , lin: .02}, 63 | firefox: {win: .83, mac: .16, lin: .01}, 64 | opera: {win: .91, mac: .03 , lin: .06}, 65 | safari: {win: .04 , mac: .96 }, 66 | iexplorer: ['win'] 67 | }; 68 | 69 | return [browser, rnd(os[browser])]; 70 | } 71 | 72 | function randomProc(arch) { 73 | var procs = { 74 | lin:['i686', 'x86_64'], 75 | mac: {'Intel' : .48, 'PPC': .01, 'U; Intel':.48, 'U; PPC' :.01}, 76 | win:['', 'WOW64', 'Win64; x64'] 77 | }; 78 | return rnd(procs[arch]); 79 | } 80 | 81 | function randomRevision(dots) { 82 | var return_val = ''; 83 | //generate a random revision 84 | //dots = 2 returns .x.y where x & y are between 0 and 9 85 | for (var x = 0; x < dots; x++) { 86 | return_val += '.' + rnd(0, 9); 87 | } 88 | return return_val; 89 | } 90 | 91 | var version_string = { 92 | net: function () { 93 | return [rnd(1, 4), rnd(0, 9), rnd(10000, 99999), rnd(0, 9)].join('.'); 94 | }, 95 | nt: function () { 96 | return rnd(5, 6) + '.' + rnd(0, 3); 97 | }, 98 | ie: function () { 99 | return rnd(7, 11); 100 | }, 101 | trident: function () { 102 | return rnd(3, 7) + '.' + rnd(0, 1); 103 | }, 104 | osx: function (delim) { 105 | return [10, rnd(5, 10), rnd(0, 9)].join(delim || '.'); 106 | }, 107 | chrome: function () { 108 | return [rnd(13, 39), 0, rnd(800, 899), 0].join('.'); 109 | }, 110 | presto: function () { 111 | return '2.9.' + rnd(160, 190); 112 | }, 113 | presto2: function () { 114 | return rnd(10, 12) + '.00'; 115 | }, 116 | safari: function () { 117 | return rnd(531, 538) + '.' + rnd(0, 2) + '.' + rnd(0,2); 118 | } 119 | }; 120 | 121 | var browser = { 122 | firefox: function firefox(arch) { 123 | //https://developer.mozilla.org/en-US/docs/Gecko_user_agent_string_reference 124 | var firefox_ver = rnd(5, 15) + randomRevision(2), 125 | gecko_ver = 'Gecko/20100101 Firefox/' + firefox_ver, 126 | proc = randomProc(arch), 127 | os_ver = (arch === 'win') ? '(Windows NT ' + version_string.nt() + ((proc) ? '; ' + proc : '') 128 | : (arch === 'mac') ? '(Macintosh; ' + proc + ' Mac OS X ' + version_string.osx() 129 | : '(X11; Linux ' + proc; 130 | 131 | return 'Mozilla/5.0 ' + os_ver + '; rv:' + firefox_ver.slice(0, -2) + ') ' + gecko_ver; 132 | }, 133 | 134 | iexplorer: function iexplorer() { 135 | var ver = version_string.ie(); 136 | 137 | if (ver >= 11) { 138 | //http://msdn.microsoft.com/en-us/library/ie/hh869301(v=vs.85).aspx 139 | return 'Mozilla/5.0 (Windows NT 6.' + rnd(1,3) + '; Trident/7.0; ' + rnd(['Touch; ', '']) + 'rv:11.0) like Gecko'; 140 | } 141 | 142 | //http://msdn.microsoft.com/en-us/library/ie/ms537503(v=vs.85).aspx 143 | return 'Mozilla/5.0 (compatible; MSIE ' + ver + '.0; Windows NT ' + version_string.nt() + '; Trident/' + 144 | version_string.trident() + ((rnd(0, 1) === 1) ? '; .NET CLR ' + version_string.net() : '') + ')'; 145 | }, 146 | 147 | opera: function opera(arch) { 148 | //http://www.opera.com/docs/history/ 149 | var presto_ver = ' Presto/' + version_string.presto() + ' Version/' + version_string.presto2() + ')', 150 | os_ver = (arch === 'win') ? '(Windows NT ' + version_string.nt() + '; U; ' + randomLang() + presto_ver 151 | : (arch === 'lin') ? '(X11; Linux ' + randomProc(arch) + '; U; ' + randomLang() + presto_ver 152 | : '(Macintosh; Intel Mac OS X ' + version_string.osx() + ' U; ' + randomLang() + ' Presto/' + 153 | version_string.presto() + ' Version/' + version_string.presto2() + ')'; 154 | 155 | return 'Opera/' + rnd(9, 14) + '.' + rnd(0, 99) + ' ' + os_ver; 156 | }, 157 | 158 | safari: function safari(arch) { 159 | var safari = version_string.safari(), 160 | ver = rnd(4, 7) + '.' + rnd(0,1) + '.' + rnd(0,10), 161 | os_ver = (arch === 'mac') ? '(Macintosh; ' + randomProc('mac') + ' Mac OS X '+ version_string.osx('_') + ' rv:' + rnd(2, 6) + '.0; '+ randomLang() + ') ' 162 | : '(Windows; U; Windows NT ' + version_string.nt() + ')'; 163 | 164 | return 'Mozilla/5.0 ' + os_ver + 'AppleWebKit/' + safari + ' (KHTML, like Gecko) Version/' + ver + ' Safari/' + safari; 165 | }, 166 | 167 | chrome: function chrome(arch) { 168 | var safari = version_string.safari(), 169 | os_ver = (arch === 'mac') ? '(Macintosh; ' + randomProc('mac') + ' Mac OS X ' + version_string.osx('_') + ') ' 170 | : (arch === 'win') ? '(Windows; U; Windows NT ' + version_string.nt() + ')' 171 | : '(X11; Linux ' + randomProc(arch); 172 | 173 | return 'Mozilla/5.0 ' + os_ver + ' AppleWebKit/' + safari + ' (KHTML, like Gecko) Chrome/' + version_string.chrome() + ' Safari/' + safari; 174 | } 175 | }; 176 | 177 | function generateUA() { 178 | var random = randomBrowserAndOS(); 179 | return browser[random[0]](random[1]); 180 | }; 181 | --------------------------------------------------------------------------------