package demo.socksv5.socksServer.core;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.dom4j.DocumentException;
import demo.socksv5.socksServer.view.SocksServerWin;
import demo.socksv5.tools.AppConfProcesser;
import demo.socksv5.tools.ConvertTool;
public class SocksServerCore {
private ServerSocket listenerForClient = null;
private String listenerPort = null;
private SocksServerWin handler = null;
private List<Integer> auList = null;
public enum StepEnum {// socks与客户端交互的几个步骤
REQUEST_FIRST, // 客户端发送的第一次请求
REQUEST_AU, // 客户端发送的验证请求
REQUEST_IP_PORT
// 客户端发送的目的信息
};
public SocksServerCore(SocksServerWin handler) throws Exception {
// 初始化socks服务器所支持的验证方式代码,目前仅支持2种
auList = new ArrayList<Integer>();
auList.add(0);// 无验证
auList.add(2);// user/password验证
this.handler = handler;
AppConfProcesser process = new AppConfProcesser(
"files/SocksServerConf.xml");
this.listenerPort = process.getElementValue("socksport");
this.listenerForClient = new ServerSocket(
Integer.parseInt(listenerPort));
}
public void beginListen() {
new MainThread().start();
}
/**
*
* @author dimmy 主线程,独立于用户界面执行,内部类,方便使用嵌套类数据
*/
private class MainThread extends Thread {
public void run() {
while (true) {
try {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Socket socketForClient = listenerForClient.accept();
new ChildThread(socketForClient).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
*
* @author dimmy 子线程,对每一个连接用户进行处理,每个连接用户对应一个子线程,内部类,方便使用嵌套类数据
*/
private class ChildThread extends Thread {
/* 子线程a内需要再建一个子线程b,a负责监听来自客户端的数据,b负责监听来自远程服务器的数据 */
private class ListenerForRmiData extends Thread {
private boolean interrupt_inner = true;
public void setInterrupt_inner(boolean interrupt_inner) {
this.interrupt_inner = interrupt_inner;
}
public void run() {
int lenRmi;
while (true) {
if (this.interrupt_inner) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
lenRmi = rmiDataInput.read(bufferRmiInput);
if (lenRmi > 0) {
handler.log("【"
+ socketForRmiServer.getInetAddress()
.getHostAddress()
+ "】发送给【"
+ socketForClient.getInetAddress()
.getHostAddress() + "】"
+ lenRmi + "个字节");
outputForUser.write(bufferRmiInput, 0, lenRmi);
outputForUser.flush();
}
} catch (IOException e) {
handler.log("与远程服务器【"+socketForRmiServer.getInetAddress().getHostAddress()+"】断开连接");
if(!socketForClient.isClosed())
{
try {
socketForClient.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
if(!socketForRmiServer.isClosed())
{
try {
socketForRmiServer.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
interuptFlag=false;
this.setInterrupt_inner(false);
}// 读远程服务器输入
} else {
break;
}
}
}
}
private ListenerForRmiData linsterRmi = null;
private String rmiServerIpAddress = null;// 远程rmi服务器的ip地址,建立于rmi服务器的连接时需要使用该地址
private short rmiServerPort = 0;// 这里的端口是远程服务器的监听端口,建立于rmi服务器的连接时需要使用该端口
private boolean flag = false;// 该标志用来标识客户端是否与远程服务器成功建立了连接,默认是false,表示没有建立连接,此时
// 线程的作用是与客户端交互,其中包括应答与响应,验证等;
// 当变成true时表明建立了连接,则这时该线程的作用就是简单的数据交换,对来的数据直接进行转发
private boolean interuptFlag = true;
private StepEnum step = null;
private Socket socketForClient = null;
private Socket socketForRmiServer = null;
private DataInputStream userDataInput = null;
private DataOutputStream outputForUser = null;
private DataInputStream rmiDataInput = null;
private DataOutputStream rmiDataOutput = null;
// private Object lock = new Object();// 互斥锁
private byte[] bufferClientInput = new byte[1024];// 中转缓冲区,用来中把从客户端读入的流写入服务器输出流
private byte[] bufferRmiInput = new byte[1024];// 中转缓冲区,与上面的过程相反
private List<Short> bufferList = null;// 缓冲区,用来缓冲客户端发送来的命令(根据协议值,用户发送的一条命令最多不会超过1k大小)
public ChildThread(Socket socketForClient) {
this.socketForClient = socketForClient;
bufferList = new ArrayList<Short>();
try {
// 获得客户端socket的输入流
userDataInput = new DataInputStream(
this.socketForClient.getInputStream());
// 获得对客户端的响应流
outputForUser = new DataOutputStream(
this.socketForClient.getOutputStream());
step = StepEnum.REQUEST_FIRST;// 线程建立时,把step置为请求第一步
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 响应客户端的第一次请求,响应格式为:request:ver(1) nmethods(1)
* methods(1-255),response:ver(1) method(1)
*
* @throws Exception
*/
private void responseForFirst() {
// 首先取得客户端第一步请求的数据(共3个字节),客户端发送的都是正数(无符号的byte),但是java中没有无符号变量,
// 所以这里只能用short来代替
// 虽然有一定浪费空间
short methods = bufferList.get(2);// 本程序只支持无验证(0)和user/password验证(2),所以该字节存放的数是0或2,如果
// 不是0或2,则服务器不支持此验证,将返回oxff(十进制是255)
short verResponse = 5;// v5的ver字段都是5
short method = 255;// 默认返回的值
// 检查socks是否支持methods所指的验证模式
for (int i = 0; i < auList.size(); i++) {
if (auList.get(i) == methods) {
method = methods;
break;
}
}
try {
short[] s = new short[2];
s[0] = verResponse;
s[1] = method;
byte[] b = ConvertTool.shortToByteArray(s);
outputForUser.write(b);
outputForUser.flush();
List<Short> list = new ArrayList<Short>();
list.add(s[0]);
list.add(s[1]);
handler.log("socks服务器响应" + ConvertTool.shortToHexString(list));
} catch (IOException e) {
e.printStackTrace();
}
if (method == 2) {
// 如果用户请求user/password验证,则置socks为第二步(REQUEST_AU)
this.step = StepEnum.REQUEST_AU;
}
if (method == 0) {
// 如果用户请求无验证模式,则置socks为第三步(REQUEST_IP_PORT)
this.step = StepEnum.REQUEST_IP_PORT;
}
if (method == 255) {
handler.log("【"+this.socketForClient.getInetAddress().getHostAddress()+"】客户端验证模式不支持");
interuptFlag = false;// 置外部条件为false后,线程会跳出while死循环,也就中断了,这时候还没有建立于远程服务器的连接,因此不用关闭那个线程
}
}
/**
* 响应客户端验证请求,指的是username/password验证
*/
public void responseForAU() {
short uLen = bufferList.get(1);
char username[] = new char[uLen];
int k = 0;
for (int i = 2; i < uLen + 2; i++) {
username[i - 2] = (char) ((int) bufferList.get(i));
k = i;
}
k++;
short pLen = bufferList.get(k);
char password[] = new char[pLen];
k++;
for (i
没有合适的资源?快使用搜索试试~ 我知道了~
socks代理服务器
共48个文件
class:25个
java:16个
xml:3个
5星 · 超过95%的资源 需积分: 35 160 下载量 121 浏览量
2011-03-18
17:05:01
上传
评论 4
收藏 358KB RAR 举报
温馨提示
java语言编写,基于socks v5协议实现socks代理服务器;其中包括一个客户端,一个应用服务器,一个socks服务器。实现无验证模式和用户名/密码验证模式,可以自由选择,使用dom4j开源工具操作xml配置文件,里面包含dom4j.jar包,添加即可使用
资源推荐
资源详情
资源评论
收起资源包目录
SocksV5Proj.rar (48个子文件)
SocksV5Proj
bin
test
Test.class 705B
demo
socksv5
client
core
ClientCore$MainThread.class 9KB
ClientCore$StepEnum.class 1KB
ClientCore.class 4KB
bean
AppConfig.class 2KB
view
ClientWin$1.class 2KB
ProxySetWin.class 6KB
ClientWin.class 6KB
RmiServerSetWin.class 4KB
server
core
ServerCore.class 2KB
ServerCore$MainThread.class 1KB
ServerCore$ChildThread.class 3KB
ServiceList.class 2KB
view
ServerWin.class 4KB
ServerSetWin.class 4KB
socksServer
core
SocksServerCore$MainThread.class 2KB
SocksServerCore$StepEnum.class 1KB
SocksServerCore$ChildThread.class 12KB
SocksServerCore$ChildThread$ListenerForRmiData.class 3KB
SocksServerCore.class 2KB
view
SocksServerSetWin.class 4KB
SocksServerWin.class 5KB
ClientAUManagerWin.class 3KB
tools
AppConfProcesser.class 4KB
ConvertTool.class 2KB
dom4j-1.6.1.jar 307KB
.settings
org.eclipse.jdt.core.prefs 629B
src
test
Test.java 1KB
demo
socksv5
client
core
ClientCore.java 11KB
bean
AppConfig.java 2KB
view
RmiServerSetWin.java 3KB
ProxySetWin.java 6KB
ClientWin.java 5KB
server
core
ServiceList.java 1KB
ServerCore.java 3KB
view
ServerSetWin.java 3KB
ServerWin.java 3KB
socksServer
core
SocksServerCore.java 17KB
view
SocksServerWin.java 4KB
SocksServerSetWin.java 3KB
ClientAUManagerWin.java 3KB
tools
AppConfProcesser.java 3KB
ConvertTool.java 2KB
.project 387B
.classpath 374B
files
ServerConf.xml 125B
AppConf.xml 272B
SocksServerConf.xml 355B
共 48 条
- 1
menglong036620
- 粉丝: 4
- 资源: 4
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
前往页