aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/net/sourceforge/jsocks/ProxyServer.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/net/sourceforge/jsocks/ProxyServer.java')
-rw-r--r--app/src/main/java/net/sourceforge/jsocks/ProxyServer.java591
1 files changed, 0 insertions, 591 deletions
diff --git a/app/src/main/java/net/sourceforge/jsocks/ProxyServer.java b/app/src/main/java/net/sourceforge/jsocks/ProxyServer.java
deleted file mode 100644
index 225149d..0000000
--- a/app/src/main/java/net/sourceforge/jsocks/ProxyServer.java
+++ /dev/null
@@ -1,591 +0,0 @@
-package net.sourceforge.jsocks;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InterruptedIOException;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.PushbackInputStream;
-import java.net.ConnectException;
-import java.net.InetAddress;
-import java.net.NoRouteToHostException;
-import java.net.ServerSocket;
-import java.net.Socket;
-
-import net.sourceforge.jsocks.server.ServerAuthenticator;
-
-/**
- SOCKS4 and SOCKS5 proxy, handles both protocols simultaniously.
- Implements all SOCKS commands, including UDP relaying.
- <p>
- In order to use it you will need to implement ServerAuthenticator
- interface. There is an implementation of this interface which does
- no authentication ServerAuthenticatorNone, but it is very dangerous
- to use, as it will give access to your local network to anybody
- in the world. One should never use this authentication scheme unless
- one have pretty good reason to do so.
- There is a couple of other authentication schemes in socks.server package.
- @see socks.server.ServerAuthenticator
-*/
-public class ProxyServer implements Runnable{
-
- ServerAuthenticator auth;
- ProxyMessage msg = null;
-
- Socket sock=null,remote_sock=null;
- ServerSocket ss=null;
- UDPRelayServer relayServer = null;
- InputStream in,remote_in;
- OutputStream out,remote_out;
-
- int mode;
- static final int START_MODE = 0;
- static final int ACCEPT_MODE = 1;
- static final int PIPE_MODE = 2;
- static final int ABORT_MODE = 3;
-
- static final int BUF_SIZE = 8192;
-
- Thread pipe_thread1,pipe_thread2;
- long lastReadTime;
-
- protected static int iddleTimeout = 180000; //3 minutes
- static int acceptTimeout = 180000; //3 minutes
-
- static PrintStream log = null;
- static Proxy proxy;
-
-
-//Public Constructors
-/////////////////////
-
-
- /**
- Creates a proxy server with given Authentication scheme.
- @param auth Authentication scheme to be used.
- */
- public ProxyServer(ServerAuthenticator auth){
- this.auth = auth;
- }
-
-//Other constructors
-////////////////////
-
- protected ProxyServer(ServerAuthenticator auth,Socket s){
- this.auth = auth;
- this.sock = s;
- mode = START_MODE;
- }
-
-//Public methods
-/////////////////
-
- /**
- Set the logging stream. Specifying null disables logging.
- */
- public static void setLog(OutputStream out){
- if(out == null){
- log = null;
- }else{
- log = new PrintStream(out,true);
- }
-
- UDPRelayServer.log = log;
- }
-
- /**
- Set proxy.
- <p>
- Allows Proxy chaining so that one Proxy server is connected to another
- and so on. If proxy supports SOCKSv4, then only some SOCKSv5 requests
- can be handled, UDP would not work, however CONNECT and BIND will be
- translated.
-
- @param p Proxy which should be used to handle user requests.
- */
- public static void setProxy(Proxy p){
- proxy =p;
- UDPRelayServer.proxy = proxy;
- }
-
- /**
- Get proxy.
- @return Proxy wich is used to handle user requests.
- */
- public static Proxy getProxy(){
- return proxy;
- }
-
- /**
- Sets the timeout for connections, how long shoud server wait
- for data to arrive before dropping the connection.<br>
- Zero timeout implies infinity.<br>
- Default timeout is 3 minutes.
- */
- public static void setIddleTimeout(int timeout){
- iddleTimeout = timeout;
- }
- /**
- Sets the timeout for BIND command, how long the server should
- wait for the incoming connection.<br>
- Zero timeout implies infinity.<br>
- Default timeout is 3 minutes.
- */
- public static void setAcceptTimeout(int timeout){
- acceptTimeout = timeout;
- }
-
- /**
- Sets the timeout for UDPRelay server.<br>
- Zero timeout implies infinity.<br>
- Default timeout is 3 minutes.
- */
- public static void setUDPTimeout(int timeout){
- UDPRelayServer.setTimeout(timeout);
- }
-
- /**
- Sets the size of the datagrams used in the UDPRelayServer.<br>
- Default size is 64K, a bit more than maximum possible size of the
- datagram.
- */
- public static void setDatagramSize(int size){
- UDPRelayServer.setDatagramSize(size);
- }
-
-
- /**
- Start the Proxy server at given port.<br>
- This methods blocks.
- */
- public void start(int port){
- start(port,5,null);
- }
-
- /**
- Create a server with the specified port, listen backlog, and local
- IP address to bind to. The localIP argument can be used on a multi-homed
- host for a ServerSocket that will only accept connect requests to one of
- its addresses. If localIP is null, it will default accepting connections
- on any/all local addresses. The port must be between 0 and 65535,
- inclusive. <br>
- This methods blocks.
- */
- public void start(int port,int backlog,InetAddress localIP){
- try{
- ss = new ServerSocket(port,backlog,localIP);
- log("Starting SOCKS Proxy on:"+ss.getInetAddress().getHostAddress()+":"
- +ss.getLocalPort());
- while(true){
- Socket s = ss.accept();
- log("Accepted from:"+s.getInetAddress().getHostName()+":"
- +s.getPort());
- ProxyServer ps = new ProxyServer(auth,s);
- (new Thread(ps)).start();
- }
- }catch(IOException ioe){
- ioe.printStackTrace();
- }finally{
- }
- }
-
- /**
- Stop server operation.It would be wise to interrupt thread running the
- server afterwards.
- */
- public void stop(){
- try{
- if(ss != null) ss.close();
- }catch(IOException ioe){
- }
- }
-
-//Runnable interface
-////////////////////
- public void run(){
- switch(mode){
- case START_MODE:
- try{
- startSession();
- }catch(IOException ioe){
- handleException(ioe);
- //ioe.printStackTrace();
- }finally{
- abort();
- if(auth!=null) auth.endSession();
- log("Main thread(client->remote)stopped.");
- }
- break;
- case ACCEPT_MODE:
- try{
- doAccept();
- mode = PIPE_MODE;
- pipe_thread1.interrupt(); //Tell other thread that connection have
- //been accepted.
- pipe(remote_in,out);
- }catch(IOException ioe){
- //log("Accept exception:"+ioe);
- handleException(ioe);
- }finally{
- abort();
- log("Accept thread(remote->client) stopped");
- }
- break;
- case PIPE_MODE:
- try{
- pipe(remote_in,out);
- }catch(IOException ioe){
- }finally{
- abort();
- log("Support thread(remote->client) stopped");
- }
- break;
- case ABORT_MODE:
- break;
- default:
- log("Unexpected MODE "+mode);
- }
- }
-
-//Private methods
-/////////////////
- private void startSession() throws IOException{
- sock.setSoTimeout(iddleTimeout);
-
- try{
- auth = auth.startSession(sock);
- }catch(IOException ioe){
- log("Auth throwed exception:"+ioe);
- auth = null;
- return;
- }
-
- if(auth == null){ //Authentication failed
- log("Authentication failed");
- return;
- }
-
- in = auth.getInputStream();
- out = auth.getOutputStream();
-
- msg = readMsg(in);
- handleRequest(msg);
- }
-
- protected void handleRequest(ProxyMessage msg)
- throws IOException{
- if(!auth.checkRequest(msg)) throw new
- SocksException(Proxy.SOCKS_FAILURE);
-
- if(msg.ip == null){
- if(msg instanceof Socks5Message){
- msg.ip = InetAddress.getByName(msg.host);
- }else
- throw new SocksException(Proxy.SOCKS_FAILURE);
- }
- log(msg);
-
- switch(msg.command){
- case Proxy.SOCKS_CMD_CONNECT:
- onConnect(msg);
- break;
- case Proxy.SOCKS_CMD_BIND:
- onBind(msg);
- break;
- case Proxy.SOCKS_CMD_UDP_ASSOCIATE:
- onUDP(msg);
- break;
- default:
- throw new SocksException(Proxy.SOCKS_CMD_NOT_SUPPORTED);
- }
- }
-
- private void handleException(IOException ioe){
- //If we couldn't read the request, return;
- if(msg == null) return;
- //If have been aborted by other thread
- if(mode == ABORT_MODE) return;
- //If the request was successfully completed, but exception happened later
- if(mode == PIPE_MODE) return;
-
- int error_code = Proxy.SOCKS_FAILURE;
-
- if(ioe instanceof SocksException)
- error_code = ((SocksException)ioe).errCode;
- else if(ioe instanceof NoRouteToHostException)
- error_code = Proxy.SOCKS_HOST_UNREACHABLE;
- else if(ioe instanceof ConnectException)
- error_code = Proxy.SOCKS_CONNECTION_REFUSED;
- else if(ioe instanceof InterruptedIOException)
- error_code = Proxy.SOCKS_TTL_EXPIRE;
-
- if(error_code > Proxy.SOCKS_ADDR_NOT_SUPPORTED || error_code < 0){
- error_code = Proxy.SOCKS_FAILURE;
- }
-
- sendErrorMessage(error_code);
- }
-
- private void onConnect(ProxyMessage msg) throws IOException{
- Socket s;
- ProxyMessage response = null;
-
- s = new Socket(msg.ip,msg.port);
-
- log("Connected to "+s.getInetAddress()+":"+s.getPort());
-
- if(msg instanceof Socks5Message){
- response = new Socks5Message(Proxy.SOCKS_SUCCESS,
- s.getLocalAddress(),
- s.getLocalPort());
- }else{
- response = new Socks4Message(Socks4Message.REPLY_OK,
- s.getLocalAddress(),s.getLocalPort());
-
- }
- response.write(out);
- startPipe(s);
- }
-
- private void onBind(ProxyMessage msg) throws IOException{
- ProxyMessage response = null;
-
- if(proxy == null)
- ss = new ServerSocket(0);
- else
- ss = new SocksServerSocket(proxy, msg.ip, msg.port);
-
- ss.setSoTimeout(acceptTimeout);
-
- log("Trying accept on "+ss.getInetAddress()+":"+ss.getLocalPort());
-
- if(msg.version == 5)
- response = new Socks5Message(Proxy.SOCKS_SUCCESS,ss.getInetAddress(),
- ss.getLocalPort());
- else
- response = new Socks4Message(Socks4Message.REPLY_OK,
- ss.getInetAddress(),
- ss.getLocalPort());
- response.write(out);
-
- mode = ACCEPT_MODE;
-
- pipe_thread1 = Thread.currentThread();
- pipe_thread2 = new Thread(this);
- pipe_thread2.start();
-
- //Make timeout infinit.
- sock.setSoTimeout(0);
- int eof=0;
-
- try{
- while((eof=in.read())>=0){
- if(mode != ACCEPT_MODE){
- if(mode != PIPE_MODE) return;//Accept failed
-
- remote_out.write(eof);
- break;
- }
- }
- }catch(EOFException eofe){
- //System.out.println("EOF exception");
- return;//Connection closed while we were trying to accept.
- }catch(InterruptedIOException iioe){
- //Accept thread interrupted us.
- //System.out.println("Interrupted");
- if(mode != PIPE_MODE)
- return;//If accept thread was not successfull return.
- }finally{
- //System.out.println("Finnaly!");
- }
-
- if(eof < 0)//Connection closed while we were trying to accept;
- return;
-
- //Do not restore timeout, instead timeout is set on the
- //remote socket. It does not make any difference.
-
- pipe(in,remote_out);
- }
-
- private void onUDP(ProxyMessage msg) throws IOException{
- if(msg.ip.getHostAddress().equals("0.0.0.0"))
- msg.ip = sock.getInetAddress();
- log("Creating UDP relay server for "+msg.ip+":"+msg.port);
- relayServer = new UDPRelayServer(msg.ip,msg.port,
- Thread.currentThread(),sock,auth);
-
- ProxyMessage response;
-
- response = new Socks5Message(Proxy.SOCKS_SUCCESS,
- relayServer.relayIP,relayServer.relayPort);
-
- response.write(out);
-
- relayServer.start();
-
- //Make timeout infinit.
- sock.setSoTimeout(0);
- try{
- while(in.read()>=0) /*do nothing*/;
- }catch(EOFException eofe){
- }
- }
-
-//Private methods
-//////////////////
-
- private void doAccept() throws IOException{
- Socket s;
- long startTime = System.currentTimeMillis();
-
- while(true){
- s = ss.accept();
- if(s.getInetAddress().equals(msg.ip)){
- //got the connection from the right host
- //Close listenning socket.
- ss.close();
- break;
- }else if(ss instanceof SocksServerSocket){
- //We can't accept more then one connection
- s.close();
- ss.close();
- throw new SocksException(Proxy.SOCKS_FAILURE);
- }else{
- if(acceptTimeout!=0){ //If timeout is not infinit
- int newTimeout = acceptTimeout-(int)(System.currentTimeMillis()-
- startTime);
- if(newTimeout <= 0) throw new InterruptedIOException(
- "In doAccept()");
- ss.setSoTimeout(newTimeout);
- }
- s.close(); //Drop all connections from other hosts
- }
- }
-
- //Accepted connection
- remote_sock = s;
- remote_in = s.getInputStream();
- remote_out = s.getOutputStream();
-
- //Set timeout
- remote_sock.setSoTimeout(iddleTimeout);
-
- log("Accepted from "+s.getInetAddress()+":"+s.getPort());
-
- ProxyMessage response;
-
- if(msg.version == 5)
- response = new Socks5Message(Proxy.SOCKS_SUCCESS, s.getInetAddress(),
- s.getPort());
- else
- response = new Socks4Message(Socks4Message.REPLY_OK,
- s.getInetAddress(), s.getPort());
- response.write(out);
- }
-
- protected ProxyMessage readMsg(InputStream in) throws IOException{
- PushbackInputStream push_in;
- if(in instanceof PushbackInputStream)
- push_in = (PushbackInputStream) in;
- else
- push_in = new PushbackInputStream(in);
-
- int version = push_in.read();
- push_in.unread(version);
-
-
- ProxyMessage msg;
-
- if(version == 5){
- msg = new Socks5Message(push_in,false);
- }else if(version == 4){
- msg = new Socks4Message(push_in,false);
- }else{
- throw new SocksException(Proxy.SOCKS_FAILURE);
- }
- return msg;
- }
-
- private void startPipe(Socket s){
- mode = PIPE_MODE;
- remote_sock = s;
- try{
- remote_in = s.getInputStream();
- remote_out = s.getOutputStream();
- pipe_thread1 = Thread.currentThread();
- pipe_thread2 = new Thread(this);
- pipe_thread2.start();
- pipe(in,remote_out);
- }catch(IOException ioe){
- }
- }
-
- private void sendErrorMessage(int error_code){
- ProxyMessage err_msg;
- if(msg instanceof Socks4Message)
- err_msg = new Socks4Message(Socks4Message.REPLY_REJECTED);
- else
- err_msg = new Socks5Message(error_code);
- try{
- err_msg.write(out);
- }catch(IOException ioe){}
- }
-
- private synchronized void abort(){
- if(mode == ABORT_MODE) return;
- mode = ABORT_MODE;
- try{
- log("Aborting operation");
- if(remote_sock != null) remote_sock.close();
- if(sock != null) sock.close();
- if(relayServer!=null) relayServer.stop();
- if(ss!=null) ss.close();
- if(pipe_thread1 != null) pipe_thread1.interrupt();
- if(pipe_thread2 != null) pipe_thread2.interrupt();
- }catch(IOException ioe){}
- }
-
- static final void log(String s){
- if(log != null){
- log.println(s);
- log.flush();
- }
- }
-
- static final void log(ProxyMessage msg){
- log("Request version:"+msg.version+
- "\tCommand: "+command2String(msg.command));
- log("IP:"+msg.ip +"\tPort:"+msg.port+
- (msg.version==4?"\tUser:"+msg.user:""));
- }
-
- private void pipe(InputStream in,OutputStream out) throws IOException{
- lastReadTime = System.currentTimeMillis();
- byte[] buf = new byte[BUF_SIZE];
- int len = 0;
- while(len >= 0){
- try{
- if(len!=0){
- out.write(buf,0,len);
- out.flush();
- }
- len= in.read(buf);
- lastReadTime = System.currentTimeMillis();
- }catch(InterruptedIOException iioe){
- if(iddleTimeout == 0) return;//Other thread interrupted us.
- long timeSinceRead = System.currentTimeMillis() - lastReadTime;
- if(timeSinceRead >= iddleTimeout - 1000) //-1s for adjustment.
- return;
- len = 0;
-
- }
- }
- }
- static final String command_names[] = {"CONNECT","BIND","UDP_ASSOCIATE"};
-
- static final String command2String(int cmd){
- if(cmd > 0 && cmd < 4) return command_names[cmd-1];
- else return "Unknown Command "+cmd;
- }
-}