使用java实现的socket代理(支持socket4和socket5)
代码如下:
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
/**
* Created with Intellij IDEA
*
* @author: jiaoyiping
* Mail: jiaoyiping@gmail.com
* Date: 2018/03/01
* Time: 22:08
* To change this template use File | Settings | Editor | File and Code Templates
*/
public class MySocket5Server implements Runnable {
private static final int SOCKS_PROTOCOL_4 = 0X04;
private static final int SOCKS_PROTOCOL_5 = 0X05;
private static final int DEFAULT_BUFFER_SIZE = 1024;
private static final byte TYPE_IPV4 = 0x01;
private static final byte TYPE_IPV6 = 0X02;
private static final byte TYPE_HOST = 0X03;
private static final byte ALLOW_PROXY = 0X5A;
private static final byte DENY_PROXY = 0X5B;
private Socket sourceSocket;
@Override
public void run() {
String remoteAddress = sourceSocket.getRemoteSocketAddress().toString();
log("process socket:" + remoteAddress);
InputStream sourceIn = null, proxyIn = null;
OutputStream sourceOut = null, proxyOut = null;
Socket proxySocket = null;
try {
sourceIn = sourceSocket.getInputStream();
sourceOut = sourceSocket.getOutputStream();
//从协议头中获取socket的类型
byte[] tmp = new byte[1];
int n = sourceIn.read(tmp);
if (n == 1) {
int protocol = tmp[0];
//socket4
if (SOCKS_PROTOCOL_4 == protocol) {
proxySocket = convertToSocket4(sourceIn, sourceOut);
} else if (SOCKS_PROTOCOL_5 == protocol) {
proxySocket = convertToSocket5(sourceIn, sourceOut);
} else {
log("Socket协议错误,不是Socket4或者Socket5");
}
//socket转换
if (null != proxySocket) {
CountDownLatch countDownLatch = new CountDownLatch(1);
proxyIn = proxySocket.getInputStream();
proxyOut = proxySocket.getOutputStream();
transfer(sourceIn, proxyOut, countDownLatch);
transfer(proxyIn, sourceOut, countDownLatch);
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
log("SOCKET ERROR: " + tmp.toString());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
closeIO(sourceIn);
closeIO(proxyIn);
closeIO(proxyOut);
closeIO(proxyIn);
closeIO(proxySocket);
closeIO(sourceSocket);
}
}
public MySocket5Server(Socket sourceSocket) {
this.sourceSocket = sourceSocket;
}
private static final void log(String message) {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(dateFormat.format(new Date()) + " - " + message);
}
private static void startServer(int port) {
log("config =>> port=" + port);
try (ServerSocket serverSocket = new ServerSocket(port)) {
Socket socket = null;
while ((socket = serverSocket.accept()) != null) {
new Thread(new MySocket5Server(socket)).start();
}
log("close socket(this never happen)");
} catch (IOException e) {
e.printStackTrace();
}
}
private Socket convertToSocket4(InputStream inputStream, OutputStream outputStream) throws IOException {
Socket proxySocket = null;
byte[] tmp = new byte[3];
inputStream.read(tmp);
// 请求协议|VN1|CD1|DSTPORT2|DSTIP4|NULL1|
int port = ByteBuffer.wrap(tmp, 1, 2).asShortBuffer().get() & 0xFFFF;
String host = getHost((byte) 0x01, inputStream);
inputStream.read();
//返回一个8字节的响应协议: |VN1|CD1|DSTPORT2|DSTIP 4|
byte[] response = new byte[8];
try {
proxySocket = new Socket(host, port);
response[1] = ALLOW_PROXY;
log("connect " + tmp[1] + "host: " + host + " ,port: " + port);
} catch (Exception e) {
response[1] = DENY_PROXY;
log("connect error,host: " + host + " ,port: " + port);
}
outputStream.write(response);
outputStream.flush();
return proxySocket;
}
private Socket convertToSocket5(InputStream inputStream, OutputStream outputStream) throws IOException {
Socket proxySocket = null;
//处理SOCKS5头信息(不支持登录)
byte[] tmp = new byte[2];
inputStream.read(tmp);
byte method = tmp[1];
if (0x02 == tmp[0]) {
method = 0x00;
inputStream.read();
}
tmp = new byte[]{0x05, method};
outputStream.write(tmp);
outputStream.flush();
byte cmd = 0;
tmp = new byte[4];
inputStream.read(tmp);
log("proxy header is:" + Arrays.toString(tmp));
cmd = tmp[1];
String host = getHost(tmp[3], inputStream);
tmp = new byte[2];
inputStream.read(tmp);
int port = ByteBuffer.wrap(tmp).asShortBuffer().get() & 0xFFFF;
log("connect host: " + host + " :port:" + port);
ByteBuffer rsv = ByteBuffer.allocate(10);
rsv.put((byte) 0x05);
Object resultTmp = null;
try {
if (0x01 == cmd) {
resultTmp = new Socket(host, port);
rsv.put((byte) 0x00);
} else if (0x02 == cmd) {
resultTmp = new ServerSocket(port);
rsv.put((byte) 0x00);
} else {
rsv.put((byte) 0x05);
resultTmp = null;
}
} catch (Exception e) {
rsv.put((byte) 0x05);
resultTmp = null;
}
rsv.put((byte) 0x00);
rsv.put((byte) 0x01);
rsv.put(sourceSocket.getLocalAddress().getAddress());
Short localPort = (short) ((sourceSocket.getLocalPort()) & 0xFFFF);
rsv.putShort(localPort);
tmp = rsv.array();
outputStream.write(tmp);
outputStream.flush();
if (null != resultTmp && 0x02 == cmd) {
ServerSocket ss = (ServerSocket) resultTmp;
try {
resultTmp = ss.accept();
} catch (Exception e) {
} finally {
closeIO(ss);
}
}
return (Socket) resultTmp;
}
private void transfer(InputStream in, OutputStream out, CountDownLatch latch) {
new Thread(() -> {
byte[] bytes = new byte[DEFAULT_BUFFER_SIZE];
int count = 0;
try {
while (0 < (count = in.read(bytes))) {
out.write(bytes, 0, count);
out.flush();
}
} catch (IOException e) {
log("转换出现错误");
e.printStackTrace();
}
if (latch != null) {
latch.countDown();
}
}).start();
}
private void closeIO(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private String getHost(byte type, InputStream inputStream) throws IOException {
String host = null;
byte[] tmp = null;
switch (type) {
case TYPE_IPV4:
tmp = new byte[4];
inputStream.read(tmp);
host = InetAddress.getByAddress(tmp).getHostAddress();
break;
case TYPE_IPV6:
tmp = new byte[16];
inputStream.read(tmp);
host = InetAddress.getByAddress(tmp).getHostAddress();
break;
case TYPE_HOST:
int count = inputStream.read();
tmp = new byte[count];
inputStream.read(tmp);
host = new String(tmp);
default:
break;
}
return host;
}
public static void main(String[] args) {
java.security.Security.setProperty("networkaddress.cache.ttl", "86400");
MySocket5Server.startServer(1033);
}
}
使用java实现的socket代理(支持socket4和socket5)的更多相关文章
- java网络编程socket\server\TCP笔记(转)
java网络编程socket\server\TCP笔记(转) 2012-12-14 08:30:04| 分类: Socket | 标签:java |举报|字号 订阅 1 TCP的开销 a ...
- java网络编程socket解析
转载:http://www.blogjava.net/landon/archive/2013/07/02/401137.html Java网络编程精解笔记2:Socket详解 Socket用法详解 在 ...
- 读懂Java中的Socket编程
Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的S ...
- 读懂Java中的Socket编程(转)
Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的S ...
- Java 反射 设计模式 动态代理机制详解 [ 转载 ]
Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...
- Java学习笔记--动态代理
动态代理 1.JDK动态代理 JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy ...
- Confluence 6 配置 Web 代理支持
这个页面中的相关平台中的内容是不被支持的.因此,Atlassian 支持不能保证能够为你提供任何支持.请注意,这个页面下面提供的信息仅为你提供参考同时也不能保证所有的的配置能正常工作.如果你按照本页面 ...
- 杨晓峰-Java核心技术-6 动态代理 反射 MD
目录 第6讲 | 动态代理是基于什么原理? 典型回答 考点分析 知识扩展 反射机制及其演进 动态代理 精选留言 Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAnd ...
- java中的socket编程
Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的S ...
随机推荐
- titlesplit源码
) UNSIGNED NOT NULL AUTO_INCREMENT, innserSessionid ), times ), channelType ), sourcetitle ), title ...
- linux command not found错误提示
错误提示:screen: command not found, 如果提示screen: command not found 命令不存在可以执行:yum install screen 或 apt-get ...
- RMAN:简单的duplicate创建新数据库 for 12c+
构建参数文件 *.db_name='test2' ##### 需要注意的地方,和rman的duplicate目标库一致 *.compatible='18.0.0' ##### 关键的地方,每个版本的模 ...
- 怎么解决BarTender因为未检测到IIS安装失败的问题
个别小伙伴在安装BarTender条码标签设计软件的时候,遇到“未检测到IIS,无法安装BarTender Web Print Server配套程序”导致安装失败的问题,本文小编给大家分享解决BarT ...
- 【QT】error: Failed to retrieve MSVC Environment from "\VC\vcvarsall.bat":
安装QT后直接打开,报错. 需要删mysql环境变量. error: Failed to retrieve MSVC Environment from "D:\Englishpath\VS2 ...
- java登录央行征信网站
package com.entrym.crawler.test; import java.util.HashMap; import java.util.Map; import org.apache.c ...
- 一些JavaScript基本函数
1.document.write(”");为 输出语句 2.JS中的注释为// 3.传统的HTML文档顺序是:document->html->(head,body) 4.一个浏览 ...
- Tomcat------如何查看80端口是否被占用
1.Window + R,打开“运行”窗口,输入cmd 2.输入netstat -nao,回车,一般来说80端口会被PID为4的程序占用 3.启动任务管理器,点击“查看”->“选择列” 4.勾选 ...
- 今天被坑了,而且被坑的好爽! 该死的UTF-8 有 BOM 格式编码
调一个项目,最后无法登录了. 排查到最后发现是cookie无法保存会话ID, 工作两年的经验这时候没用上. 开始一以为是PHP.ini的配置错了. 考虑过域名,浏览器问题. 脚本BUG. 最后最后一步 ...
- Python对象(下)
前面一篇文章介绍了一些Python对象的基本概念,这篇接着来看看Python对象相关的一些内容. Python对象的比较 Python对象有三个要素:身份,类型和值,所以我们就分别从这三个角度出发看看 ...