代码如下:

    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)的更多相关文章

  1. java网络编程socket\server\TCP笔记(转)

    java网络编程socket\server\TCP笔记(转) 2012-12-14 08:30:04|  分类: Socket |  标签:java  |举报|字号 订阅     1 TCP的开销 a ...

  2. java网络编程socket解析

    转载:http://www.blogjava.net/landon/archive/2013/07/02/401137.html Java网络编程精解笔记2:Socket详解 Socket用法详解 在 ...

  3. 读懂Java中的Socket编程

    Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的S ...

  4. 读懂Java中的Socket编程(转)

    Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的S ...

  5. Java 反射 设计模式 动态代理机制详解 [ 转载 ]

    Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...

  6. Java学习笔记--动态代理

    动态代理 1.JDK动态代理 JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy ...

  7. Confluence 6 配置 Web 代理支持

    这个页面中的相关平台中的内容是不被支持的.因此,Atlassian 支持不能保证能够为你提供任何支持.请注意,这个页面下面提供的信息仅为你提供参考同时也不能保证所有的的配置能正常工作.如果你按照本页面 ...

  8. 杨晓峰-Java核心技术-6 动态代理 反射 MD

    目录 第6讲 | 动态代理是基于什么原理? 典型回答 考点分析 知识扩展 反射机制及其演进 动态代理 精选留言 Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAnd ...

  9. java中的socket编程

    Socket,又称为套接字,Socket是计算机网络通信的基本的技术之一.如今大多数基于网络的软件,如浏览器,即时通讯工具甚至是P2P下载都是基于Socket实现的.本文会介绍一下基于TCP/IP的S ...

随机推荐

  1. shell特殊符号cut命令 sort_wc_uniq命令 tee_tr_split命令 shell特殊符号

    shell特殊符号cut命令 特殊符号 *  通配符,任意个任意字符 ? 任意一个字符 # 注释字符 \  脱义字符 c=\$a\$b echo  $c | 管道符 cat  1.txt |less ...

  2. Linux 找不到php.ini

    在部署环境中利用phpinfo()查看,显示php.ini 路径为/usr/local/php5/lib 但是到对应路径中,找不到php.ini文件,在网上找到相关方法,留下备注. Configura ...

  3. 【LSTM】Understanding-LSTMs

    http://colah.github.io/posts/2015-08-Understanding-LSTMs/

  4. MathType如何设置标尺的单位

    MathType在编辑公式的时候,经常会需要将公式对齐.在将公式对齐的这个过程中,有时候会用到标尺,这样可以更精确的定位公式的位置.我们在使用标尺的时候,有时候会发现标尺上显示的是英寸,而我们平常已经 ...

  5. WebGL 绘制和变换

    1.使用缓冲区对象向顶点着色器传入多个顶点的数据,需要遵循以下五个步骤: 1.1 创建缓冲区对象(gl.createBuffer()). 1.2 绑定缓冲区对象(gl.bindBuffer()). 1 ...

  6. [转] NGUI自适应

    很多做移动终端开发的童鞋都可能遇到一个问题,就是如何自适应其实NGUI已经能帮我们实现,下面就告诉大家怎么整这个自适应.1,create a new ui 2,uiroot下添加uipanel(scr ...

  7. Git------解决右键不显示Git Bash Here问题

    步骤: 1.通过在“运行”中输入‘regedit’,打开注册表. 2.找到[HKEY_CLASSES_ROOT\Directory\Background]. 3.在[shell]下右键-新建项[ope ...

  8. MySQL --- 计算指定日期为当月的第几周

    SET @d=NOW(); ; 啦啦啦

  9. Go之go与channel组合使用

    1,等待一个事件 <-ch 将一直阻塞,直到ch被关闭 或者 ch中可以取出值 为止 所以到第17行之后会去执行go后面的func()匿名函数,在里面给ch赋值后(或者close(ch))后,才 ...

  10. Python 扩展知识

    Python 练习题 Python 编程习惯 Python 转义字符 Python 格式化输出 Python 列表表达式 Python 生成器表达式 Python 序列化 Python2 与 Pyth ...