实现代理proxy

Posted 方帅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现代理proxy相关的知识,希望对你有一定的参考价值。

 用户在哪些情况下是需要设置网络代理呢?

1. 内网上不了外网,需要连接能上外网的内网电脑做代理,就能上外网;多个电脑共享上外网,就要用代理; 
2.有些网页被封,通过国外的代理就能看到这被封的网站;
3.想隐藏真实IP;

4. 想加快访问网站速度,在网络出现拥挤或故障时,可通过代理服务器访问目的网站。比如A要访问C网站,但A到C网络出现问题,可以通过绕道,假设B是代理服务器,A可通过B, 再由B到C。

我们app的大多数用户情况是第一种.我们参考qq和chrome的插件switchysharp设置代理的方式来设计的界面

 

 我们的项目是基于node-webkit技术进行开发的。

对于浏览器直接发送的请求设置代理可以直接设置chrome.proxy

1                 if (proxy.proxyType == 0) {//不使用代理
2                     chrome.proxy.settings.set({ \'value\': { \'mode\': \'direct\' } }, function (e) { console.log(e) });
3                 } else if (proxy.proxyType == 1) {//使用http代理
4                     chrome.proxy.settings.set({ \'value\': { \'mode\': \'fixed_servers\', rules: { singleProxy: { scheme: \'http\', host: proxy.host, port: proxy.port }, bypassList: null } } }, function (e) { console.log(e) });
5                 } else if (proxy.proxyType == 2) {//使用socks代理,可以支持版本4或者5
6                     chrome.proxy.settings.set({ \'value\': { \'mode\': \'fixed_servers\', rules: { singleProxy: { scheme: \'socks\' + proxy.ver, host: proxy.host, port: proxy.port }, bypassList: null } } }, function (e) { console.log(e) });
7                 } else if (proxy.proxyType == 3) {//使用系统代理
8                     chrome.proxy.settings.set({ \'value\': { \'mode\': \'system\' } }, function (e) { console.log(e) });

而程序内部使用nodejs发送的请求需要在发送请求时通过option进行配置,才能走代理网络

 1          var options = {
 2                 hostname: Common.Config.addrInfo.openApi,
 3                 path: \'/api/Author/Article/Collected?skip=\' + skip + \' & rows=\' + this.pageSize,
 4                 method : "GET";
 5                 headers: {
 6                     \'Accept\' : "application/json",
 7                     \'Authorization\': \'Bearer \' + index.userInfo.token
 8                 }
 9             };
10 
11             var req = require(\'http\').request(HttpUtil.setProxy(options), function (res) {
12                 var err = HttpUtil.resStatus(options, res);
13                 clearTimeout(timeoutEventId);
14                 if (err) {
15                     callback(err);
16                     return;
17                 }
18                 var resData = [];
19                 res.setEncoding(\'utf8\');
20                 res.on(\'data\', function (chunk) {
21                     resData.push(chunk);
22                 }).on("end", function () {
23                     callback(null, resData.join(""));
24                 });
25             });
26             req.on(\'error\', function (e) {
27                 clearTimeout(timeoutEventId);
28                 callback(HttpUtil.reqStatus(options, e));
29                 req.end();
30             });
31             req.on(\'timeout\', function (e) {
32                 clearTimeout(timeoutEventId);
33                 callback(HttpUtil.reqStatus(options, e));
34             });
35             req.end();
36         }      
37     static setProxy(options) {//设置代理信息
38             if (this.proxy) {
39                 if (this.proxy.proxyType == 1 || (this.proxy.proxyType == 3 && this.proxy.host && this.proxy.sysProxyType == "PROXY")) {
40                     options.path = "http://" + options.hostname + options.path;
41                     options.hostname = null;
42                     options.host = this.proxy.host;
43                     options.port = this.proxy.port;
44                 } else if (this.proxy.proxyType == 2 || (this.proxy.proxyType == 3 && this.proxy.host && this.proxy.sysProxyType == "SOCKS")) {
45                     try {
46                         if (!this.SocksProxyAgent)
47                             this.SocksProxyAgent = require(\'socks-proxy-agent\');//引用socks代理配置模块
48                     } catch (e) {
49                         this.SocksProxyAgent = null;
50                     }
51                     if (this.SocksProxyAgent) {
52                         var agent = new this.SocksProxyAgent("socks" + this.proxy.ver + "://" + this.proxy.host + ":" + this.proxy.port);
53                         options.agent = agent;
54                     }
55                 }
56             }
57             return options;
58         }           

 但是经过实践证明这个方法解决不了很多网络代理用户请求我们服务器接口失败的问题。

我们又找到了request模块,经过在有问题的电脑上进行测试这个模块是可以访问成功的。

 1          var options1 = {
 2                 url: \'http://openapi.axeslide.com/api/TemplateTypes\',
 3                 proxy: "http://10.22.138.21:8080",
 4                 headers: {
 5                     \'User-Agent\': \'request\',
 6                     \'Authorization\': \'Bearer \' + index.userInfo.token,
 7                     \'Accept\' :"application/json"
 8                 }
 9             };
10             this.request.get(options1, function (error, response, body) {
11                 if (!error && response.statusCode == 200) {
12                     console.log(response,body,"ok") 
13                 } else {
14                     console.log(response,error, "err") 
15                 }
16             })

但是不管是之前的方式还是现在的request模板,在使用socks代理时,接收的数据量超过一定值时返回就会出现问题,然后把之前的socks-proxy-agent

又换了socks5-http-client做测试解决了该问题。

现在说一下测试工具,fiddler和node搭建的socks代理服务器

fiddler相信对大家来对并不陌生,先打开fiddler options选项,然后配置下代理信息,主要是端口号,这里可以设置是否设置成系统代理,设置之后需要重新启动fiddler,如果浏览器配置成走9999 所有的请求fiddler都会抓取到。

 

搭建socks代理可以从网上找现成的代码,node搭建的。大家也可以下载 http://files.cnblogs.com/files/fangsmile/socks5.zip ,下载后运行node proxy

 

 

下面附一段switchysharp的实现代码:

 1 ProxyPlugin.setProxy = function (proxyMode, proxyString, proxyExceptions, proxyConfigUrl) {
 2     if (ProxyPlugin.disabled) return 0;
 3     var config;
 4     ProxyPlugin.proxyMode = Settings.setValue(\'proxyMode\', proxyMode);
 5     ProxyPlugin.proxyServer = Settings.setValue(\'proxyServer\', proxyString);
 6     ProxyPlugin.proxyExceptions = Settings.setValue(\'proxyExceptions\', proxyExceptions);
 7     ProxyPlugin.proxyConfigUrl = Settings.setValue(\'proxyConfigUrl\', proxyConfigUrl);
 8     switch (proxyMode) {
 9         case \'system\':
10             config = {mode:"system"};
11             break;
12         case \'direct\':
13             config = {mode:"direct"};
14             break;
15         case \'manual\':
16             var tmpbypassList = [];
17             var proxyExceptionsList = ProxyPlugin.proxyExceptions.split(\';\');
18             var proxyExceptionListLength = proxyExceptionsList.length;
19             for (var i = 0; i < proxyExceptionListLength; i++) {
20                 tmpbypassList.push(proxyExceptionsList[i].trim())
21             }
22             proxyExceptionsList = null;
23             var profile = ProfileManager.parseProxyString(proxyString);
24             if (profile.useSameProxy) {
25                 config = {
26                     mode:"fixed_servers",
27                     rules:{
28                         singleProxy:ProxyPlugin._parseProxy(profile.proxyHttp),
29                         bypassList:tmpbypassList
30                     }
31                 };
32             }
33             else {
34                 var socksProxyString;
35                 if (profile.proxySocks && !profile.proxyHttp && !profile.proxyFtp && !profile.proxyHttps) {
36                     socksProxyString = profile.socksVersion == 4 ? \'socks=\' + profile.proxySocks : \'socks5=\' + profile.proxySocks;
37                     config = {
38                         mode:"fixed_servers",
39                         rules:{
40                             singleProxy:ProxyPlugin._parseProxy(socksProxyString),
41                             bypassList:tmpbypassList
42                         }
43                     }
44 
45                 }
46                 else {
47                     config = {
48                         mode:"fixed_servers",
49                         rules:{
50                             bypassList:tmpbypassList
51                         }
52                     };
53                     if (profile.proxySocks) {
54                         socksProxyString = profile.socksVersion == 4 ? \'socks=\' + profile.proxySocks : \'socks5=\' + profile.proxySocks;
55                         config.rules.fallbackProxy = ProxyPlugin._parseProxy(socksProxyString);
56                     }
57                     if (profile.proxyHttp)
58                         config.rules.proxyForHttp = ProxyPlugin._parseProxy(profile.proxyHttp);
59                     if (profile.proxyFtp)
60                         config.rules.proxyForFtp = ProxyPlugin._parseProxy(profile.proxyFtp);
61                     if (profile.proxyHttps)
62                         config.rules.proxyForHttps = ProxyPlugin._parseProxy(profile.proxyHttps);
63                 }
64             }
65             tmpbypassList = null;
66             break;
67         case \'auto\':
68             if (ProxyPlugin.proxyConfigUrl == memoryPath) {
69                 config = {
70                     mode:"pac_script",
71                     pacScript:{
72                         data:Settings.getValue(\'pacScriptData\', \'\')
73                     }
74                 };
75                 Settings.setValue(\'pacScriptData\', \'\');
76             }
77             else {
78                 config = {
79                     mode:"pac_script",
80                     pacScript:{
81                         url:ProxyPlugin.proxyConfigUrl
82                     }
83                 }
84             }
85             break;
86     }
87     ProxyPlugin.mute = true;
88     ProxyPlugin._proxy.settings.set({\'value\':config}, function () {
89         ProxyPlugin.mute = false;
90         if (ProxyPlugin.setProxyCallback != undefined) {
91             ProxyPlugin.setProxyCallback();
92             ProxyPlugin.setProxyCallback = undefined;
93         }
94     });
95     profile = null;
96     config = null;
97     return 0;
98 };
View Code

 

以上是关于实现代理proxy的主要内容,如果未能解决你的问题,请参考以下文章

Extjs使用商店代理api; CRUD

代理模式

如何使用 dart 实现委托/代理?

动态代理之JDK Proxy浅析

阿里四面:你知道Spring AOP创建Proxy的过程吗?

设计模式之代理模式(Proxy)详解及代码示例