切换代理的chrome插件

我一直用ssh tunnel翻墙,在firefox下用foxyproxy一直很正常。但是在chrome下就总是悲剧。

我的需求很简单,我需要三种上网模式,并能很方便的在几种模式下切换。

* 完全禁用代理
* 所有的请求都通过ssh tunnel代理
* 能根据网站url自动的决定是否使用ssh tunnel代理(我通过pac文件来实现)

Chrome下有个Switchy插件,能够满足前两点需求,但是最后一点,无论是我使用pac文件,还是使用它自身的Auto Mode,都不好使。
前天花1个小时看了一下Switchy的源代码,没看出什么头绪。昨天索性就自己写了一个,发现其实挺简单的。
不得不说,google做的东西就是好,不光chrome本身做得好,连它提供的外部接口使用起来也是方便快捷。

主要参考了三篇文章,都是官网提供的:

  1. 入门级教程, 主要了解了开发插件的大致过程,比如怎样加载和更新插件。

  2. 关于browserAction的例子,主要了解如何处理插件图标的点击事件,如何给插件设置图标。

  3. chome.proxy接口文档,文档中已经提供了足够丰富的如何设置代理样例代码。

我自己的插件基本上就是在browserAction的例子上改的,然后盗用了Switchy的三张图片。
除去图片一共就三个文件,也没多少代码,全贴出来。
实现的功能就是点击插件按钮时在三种上网模式下依次切换。
而我使用的pac文件的网址,以及ssh tunnel的地址和端口号,都是写死在代码里面的。

  1. manifest.json

    {
      "name": "tunnel switch",
      "version": "1.0",
      "background_page": "background.html",
      "permissions": [
        "tabs", "http://*/*", "proxy"
      ],
      "browser_action": {
          "name": "Click to change the proxy"
      },
      "content_security_policy": "default-src 'self'"
    }
    
  2. background.html

    <!doctype html>
    <html>
      <head>
        <title>Background Page</title>
        <script src="background.js"></script>
      </head>
      <body>
      </body>
    </html>
    
  3. background.js

    var currentProxyType = 'pac';
    
    function changeProxy(type){
        currentProxyType = type;
        if(type=='pac'){
            var config = {
              mode: "pac_script",
              pacScript: {
                  url:"file:///Users/oylbin/oylbin/proxy.pac?"+(new Date).getTime(),
                  mandatory:true
              }
            };
        }else if(type=='tunnel'){
            var config = {
                mode: "fixed_servers",
                rules: {
                    singleProxy: {
                                      scheme: "socks5",
                                      host: "127.0.0.1",
                                      port: 8527
                                  },
                    bypassList: ["foobar.com"]
                }
            };
        }else{
            type='direct';
            var config = {
                mode: "direct"
            };
        }
        chrome.proxy.settings.set({value: config, scope: 'regular'},function() {});
        chrome.browserAction.setIcon({path:type+".png"});
    }
    
    function onIconClicked() {
        if(currentProxyType=='pac'){
            changeProxy('tunnel');
        }else if(currentProxyType=='tunnel'){
            changeProxy('direct');
        }else if(currentProxyType=='direct'){
            changeProxy('pac');
        }
    }
    chrome.browserAction.onClicked.addListener(onIconClicked);
    changeProxy('pac');
    

最后,提供一个我使用的proxy.pac文件的样例,如果要加网址规则,加到site_list 和 exp_list即可

function FindProxyForURL(url, host)
{
    url = url.toLowerCase();
    host = host.toLowerCase();

    // whole site
    var site_list = [
        'bitsnoop.com'
        ,'blogger.com'
        ,'blogspot.com'
    ];

    var exp_list = [
     'http(s)?://(sites|groups|picasaweb|feedproxy|fusion)\.google\.com/.*',
     'http://www\.google\.com/(((search|url)\?)|analytics|calendar|profile).*',
     'http://[^/]*/search\?q=cache.*'
    ];

    for(var index = 0;index<site_list.length;index++){
         if(host==site_list[index] ||
             shExpMatch(host, "*." + site_list[index])){
            return "SOCKS5 127.0.0.1:8527";
         }
    }
    for(var index = 0;index<exp_list.length;index++){
        var re = new RegExp(exp_list[index]);
        if(url.match(re)){
            return "SOCKS5 127.0.0.1:8527";
        }
    }
    return "DIRECT";
}

Comments