工作需要,需要用Java Socket穿越SOCKS代理服务器,网上胡乱搜一通,别怪哥说话难听,什么TMD的System.getProperties().put(......),java.net.Proxy全都不行,气急败坏,哥直接看协议去。
中文版SOCK4协议地址:http://zh.wikipedia.org/wiki/SOCKS
英文版SOCK5协议地址:http://www.ietf.org/rfc/rfc1928.txt
要想穿越代理服务器,必须要与代理服务器进行TCP连接,并实现一次或者多次握手过程。
拿SOCK4协议举例(本人代理环境为SOCK4,经测试已成功穿越)。
仔细阅读SOCK4协议,客户端要想穿越SOCK4协议与外网相连,需有一次握手过程,即客户端需向代理服务器发送一个字节序列,根据协议规范,我发送的字节序列为:
{0x04,0x01,0x1f,(byte)0x41,(byte)0xd3,(byte)0x8a,(byte)0xe0,0x35,0x00}
其中:
0X04:协议版本
0X01:CONNECT请求(0X02时为BIND请求)
0X1F 0X41:访问的外网端口(8001)
0XD3 0X8A 0XE0 0X35:访问的外网IP地址(211.138.224.53)
0X00:(相当于结束位的标志)
连接成功后,服务器端会返回应答序列,序列含义见SOCKS4协议(详细不再讲解)
握手成功后,Socket就可以按照和一般方式进行与外网服务器的通信了。
最后给出实现代码:
//穿越Socke4代理服务 Socket socket = new Socket("isasrv.hn.cmcc",1080);//代理服务器地址和端口 byte[] datas = {0x04,0x01,0x1f,(byte)0x41,(byte)0xd3,(byte)0x8a,(byte)0xe0,0x35,0x00};//发送的握手字节序列 OutputStream os = socket.getOutputStream(); os.write(datas); byte[] receive = new byte[8]; //服务端返回的字节 InputStream is = socket.getInputStream(); int count = 0; if((count = is.read(receive)) > 0) { //一定要先读服务器返回的字节序列 //System.out.println(count); for(byte b : receive) { System.out.println(Integer.toHexString((int)b)); } } os.write(...);//按照常规方式读写数据吧 receive = new byte[140]; is.close(); os.close(); socket.close();
在资料搜寻过程中发现了一个可以利用的现成类库jsocks,项目地址:http://jsocks.sourceforge.net/
有兴趣的可以去看下,实现机制完全相同。
有什么问题,留言吧!切记,出现问题不要幻想网上会给你指路,最终还是要靠自己!