1 package socks; 2 import socks.server.ServerAuthenticator; 3 import java.net.*; 4 import java.io.*; 5 6 19 public class ProxyServer implements Runnable { 20 21 ServerAuthenticator auth; 22 ProxyMessage msg = null; 23 24 Socket sock=null,remote_sock=null; 25 ServerSocket ss=null; 26 UDPRelayServer relayServer = null; 27 InputStream in,remote_in; 28 OutputStream out,remote_out; 29 30 int mode; 31 static final int START_MODE = 0; 32 static final int ACCEPT_MODE = 1; 33 static final int PIPE_MODE = 2; 34 static final int ABORT_MODE = 3; 35 36 static final int BUF_SIZE = 8192; 37 38 Thread pipe_thread1,pipe_thread2; 39 long lastReadTime; 40 41 static int iddleTimeout = 180000; static int acceptTimeout = 180000; 44 static PrintStream log = null; 45 static Proxy proxy; 46 47 48 51 52 56 public ProxyServer(ServerAuthenticator auth){ 57 this.auth = auth; 58 } 59 60 63 ProxyServer(ServerAuthenticator auth,Socket s){ 64 this.auth = auth; 65 this.sock = s; 66 mode = START_MODE; 67 } 68 69 72 75 public static void setLog(OutputStream out){ 76 if(out == null){ 77 log = null; 78 }else{ 79 log = new PrintStream(out,true); 80 } 81 82 UDPRelayServer.log = log; 83 } 84 85 95 public static void setProxy(Proxy p){ 96 proxy =p; 97 UDPRelayServer.proxy = proxy; 98 } 99 100 104 public static Proxy getProxy(){ 105 return proxy; 106 } 107 108 114 public static void setIddleTimeout(int timeout){ 115 iddleTimeout = timeout; 116 } 117 123 public static void setAcceptTimeout(int timeout){ 124 acceptTimeout = timeout; 125 } 126 127 132 public static void setUDPTimeout(int timeout){ 133 UDPRelayServer.setTimeout(timeout); 134 } 135 136 141 public static void setDatagramSize(int size){ 142 UDPRelayServer.setDatagramSize(size); 143 } 144 145 146 150 public void start(int port){ 151 start(port,5,null); 152 } 153 154 163 public void start(int port,int backlog,InetAddress localIP){ 164 try{ 165 ss = new ServerSocket(port,backlog,localIP); 166 log("Starting SOCKS Proxy on:"+ss.getInetAddress().getHostAddress()+":" 167 +ss.getLocalPort()); 168 while(true){ 169 Socket s = ss.accept(); 170 log("Accepted from:"+s.getInetAddress().getHostName()+":" 171 +s.getPort()); 172 ProxyServer ps = new ProxyServer(auth,s); 173 (new Thread (ps)).start(); 174 } 175 }catch(IOException ioe){ 176 ioe.printStackTrace(); 177 }finally{ 178 } 179 } 180 181 185 public void stop(){ 186 try{ 187 if(ss != null) ss.close(); 188 }catch(IOException ioe){ 189 } 190 } 191 192 public void run(){ 195 switch(mode){ 196 case START_MODE: 197 try{ 198 startSession(); 199 }catch(IOException ioe){ 200 handleException(ioe); 201 }finally{ 203 abort(); 204 if(auth!=null) auth.endSession(); 205 log("Main thread(client->remote)stopped."); 206 } 207 break; 208 case ACCEPT_MODE: 209 try{ 210 doAccept(); 211 mode = PIPE_MODE; 212 pipe_thread1.interrupt(); pipe(remote_in,out); 215 }catch(IOException ioe){ 216 handleException(ioe); 218 }finally{ 219 abort(); 220 log("Accept thread(remote->client) stopped"); 221 } 222 break; 223 case PIPE_MODE: 224 try{ 225 pipe(remote_in,out); 226 }catch(IOException ioe){ 227 }finally{ 228 abort(); 229 log("Support thread(remote->client) stopped"); 230 } 231 break; 232 case ABORT_MODE: 233 break; 234 default: 235 log("Unexpected MODE "+mode); 236 } 237 } 238 239 private void startSession() throws IOException{ 242 sock.setSoTimeout(iddleTimeout); 243 244 try{ 245 auth = auth.startSession(sock); 246 }catch(IOException ioe){ 247 log("Auth throwed exception:"+ioe); 248 auth = null; 249 return; 250 } 251 252 if(auth == null){ log("Authentication failed"); 254 return; 255 } 256 257 in = auth.getInputStream(); 258 out = auth.getOutputStream(); 259 260 msg = readMsg(in); 261 handleRequest(msg); 262 } 263 264 private void handleRequest(ProxyMessage msg) 265 throws IOException{ 266 if(!auth.checkRequest(msg)) throw new 267 SocksException(Proxy.SOCKS_FAILURE); 268 269 if(msg.ip == null){ 270 if(msg instanceof Socks5Message){ 271 msg.ip = InetAddress.getByName(msg.host); 272 }else 273 throw new SocksException(Proxy.SOCKS_FAILURE); 274 } 275 log(msg); 276 277 switch(msg.command){ 278 case Proxy.SOCKS_CMD_CONNECT: 279 onConnect(msg); 280 break; 281 case Proxy.SOCKS_CMD_BIND: 282 onBind(msg); 283 break; 284 case Proxy.SOCKS_CMD_UDP_ASSOCIATE: 285 onUDP(msg); 286 break; 287 default: 288 throw new SocksException(Proxy.SOCKS_CMD_NOT_SUPPORTED); 289 } 290 } 291 292 private void handleException(IOException ioe){ 293 if(msg == null) return; 295 if(mode == ABORT_MODE) return; 297 if(mode == PIPE_MODE) return; 299 300 int error_code = Proxy.SOCKS_FAILURE; 301 302 if(ioe instanceof SocksException) 303 error_code = ((SocksException)ioe).errCode; 304 else if(ioe instanceof NoRouteToHostException) 305 error_code = Proxy.SOCKS_HOST_UNREACHABLE; 306 else if(ioe instanceof ConnectException) 307 error_code = Proxy.SOCKS_CONNECTION_REFUSED; 308 else if(ioe instanceof InterruptedIOException) 309 error_code = Proxy.SOCKS_TTL_EXPIRE; 310 311 if(error_code > Proxy.SOCKS_ADDR_NOT_SUPPORTED || error_code < 0){ 312 error_code = Proxy.SOCKS_FAILURE; 313 } 314 315 sendErrorMessage(error_code); 316 } 317 318 private void onConnect(ProxyMessage msg) throws IOException{ 319 Socket s; 320 ProxyMessage response = null; 321 322 if(proxy == null) 323 s = new Socket(msg.ip,msg.port); 324 else 325 s = new SocksSocket(proxy,msg.ip,msg.port); 326 327 log("Connected to "+s.getInetAddress()+":"+s.getPort()); 328 329 if(msg instanceof Socks5Message){ 330 response = new Socks5Message(Proxy.SOCKS_SUCCESS, 331 s.getLocalAddress(), 332 s.getLocalPort()); 333 }else{ 334 response = new Socks4Message(Socks4Message.REPLY_OK, 335 s.getLocalAddress(),s.getLocalPort()); 336 337 } 338 response.write(out); 339 startPipe(s); 340 } 341 342 private void onBind(ProxyMessage msg) throws IOException{ 343 ProxyMessage response = null; 344 345 if(proxy == null) 346 ss = new ServerSocket(0); 347 else 348 ss = new SocksServerSocket(proxy, msg.ip, msg.port); 349 350 ss.setSoTimeout(acceptTimeout); 351 352 log("Trying accept on "+ss.getInetAddress()+":"+ss.getLocalPort()); 353 354 if(msg.version == 5) 355 response = new Socks5Message(Proxy.SOCKS_SUCCESS,ss.getInetAddress(), 356 ss.getLocalPort()); 357 else 358 response = new Socks4Message(Socks4Message.REPLY_OK, 359 ss.getInetAddress(), 360 ss.getLocalPort()); 361 response.write(out); 362 363 mode = ACCEPT_MODE; 364 365 pipe_thread1 = Thread.currentThread(); 366 pipe_thread2 = new Thread (this); 367 pipe_thread2.start(); 368 369 sock.setSoTimeout(0); 371 int eof=0; 372 373 try{ 374 while((eof=in.read())>=0){ 375 if(mode != ACCEPT_MODE){ 376 if(mode != PIPE_MODE) return; 378 remote_out.write(eof); 379 break; 380 } 381 } 382 }catch(EOFException eofe){ 383 return; }catch(InterruptedIOException iioe){ 386 if(mode != PIPE_MODE) 389 return; }finally{ 391 } 393 394 if(eof < 0) return; 396 397 400 pipe(in,remote_out); 401 } 402 403 private void onUDP(ProxyMessage msg) throws IOException{ 404 if(msg.ip.getHostAddress().equals("0.0.0.0")) 405 msg.ip = sock.getInetAddress(); 406 log("Creating UDP relay server for "+msg.ip+":"+msg.port); 407 relayServer = new UDPRelayServer(msg.ip,msg.port, 408 Thread.currentThread(),sock,auth); 409 410 ProxyMessage response; 411 412 response = new Socks5Message(Proxy.SOCKS_SUCCESS, 413 relayServer.relayIP,relayServer.relayPort); 414 415 response.write(out); 416 417 relayServer.start(); 418 419 sock.setSoTimeout(0); 421 try{ 422 while(in.read()>=0) ; 423 }catch(EOFException eofe){ 424 } 425 } 426 427 430 private void doAccept() throws IOException{ 431 Socket s; 432 long startTime = System.currentTimeMillis(); 433 434 while(true){ 435 s = ss.accept(); 436 if(s.getInetAddress().equals(msg.ip)){ 437 ss.close(); 440 break; 441 }else if(ss instanceof SocksServerSocket){ 442 s.close(); 444 ss.close(); 445 throw new SocksException(Proxy.SOCKS_FAILURE); 446 }else{ 447 if(acceptTimeout!=0){ int newTimeout = acceptTimeout-(int)(System.currentTimeMillis()- 449 startTime); 450 if(newTimeout <= 0) throw new InterruptedIOException( 451 "In doAccept()"); 452 ss.setSoTimeout(newTimeout); 453 } 454 s.close(); } 456 } 457 458 remote_sock = s; 460 remote_in = s.getInputStream(); 461 remote_out = s.getOutputStream(); 462 463 remote_sock.setSoTimeout(iddleTimeout); 465 466 log("Accepted from "+s.getInetAddress()+":"+s.getPort()); 467 468 ProxyMessage response; 469 470 if(msg.version == 5) 471 response = new Socks5Message(Proxy.SOCKS_SUCCESS, s.getInetAddress(), 472 s.getPort()); 473 else 474 response = new Socks4Message(Socks4Message.REPLY_OK, 475 s.getInetAddress(), s.getPort()); 476 response.write(out); 477 } 478 479 private ProxyMessage readMsg(InputStream in) throws IOException{ 480 PushbackInputStream push_in; 481 if(in instanceof PushbackInputStream) 482 push_in = (PushbackInputStream) in; 483 else 484 push_in = new PushbackInputStream(in); 485 486 int version = push_in.read(); 487 push_in.unread(version); 488 489 490 ProxyMessage msg; 491 492 if(version == 5){ 493 msg = new Socks5Message(push_in,false); 494 }else if(version == 4){ 495 msg = new Socks4Message(push_in,false); 496 }else{ 497 throw new SocksException(Proxy.SOCKS_FAILURE); 498 } 499 return msg; 500 } 501 502 private void startPipe(Socket s){ 503 mode = PIPE_MODE; 504 remote_sock = s; 505 try{ 506 remote_in = s.getInputStream(); 507 remote_out = s.getOutputStream(); 508 pipe_thread1 = Thread.currentThread(); 509 pipe_thread2 = new Thread (this); 510 pipe_thread2.start(); 511 pipe(in,remote_out); 512 }catch(IOException ioe){ 513 } 514 } 515 516 private void sendErrorMessage(int error_code){ 517 ProxyMessage err_msg; 518 if(msg instanceof Socks4Message) 519 err_msg = new Socks4Message(Socks4Message.REPLY_REJECTED); 520 else 521 err_msg = new Socks5Message(error_code); 522 try{ 523 err_msg.write(out); 524 }catch(IOException ioe){} 525 } 526 527 private synchronized void abort(){ 528 if(mode == ABORT_MODE) return; 529 mode = ABORT_MODE; 530 try{ 531 log("Aborting operation"); 532 if(remote_sock != null) remote_sock.close(); 533 if(sock != null) sock.close(); 534 if(relayServer!=null) relayServer.stop(); 535 if(ss!=null) ss.close(); 536 if(pipe_thread1 != null) pipe_thread1.interrupt(); 537 if(pipe_thread2 != null) pipe_thread2.interrupt(); 538 }catch(IOException ioe){} 539 } 540 541 static final void log(String s){ 542 if(log != null){ 543 log.println(s); 544 log.flush(); 545 } 546 } 547 548 static final void log(ProxyMessage msg){ 549 log("Request version:"+msg.version+ 550 "\tCommand: "+command2String(msg.command)); 551 log("IP:"+msg.ip +"\tPort:"+msg.port+ 552 (msg.version==4?"\tUser:"+msg.user:"")); 553 } 554 555 private void pipe(InputStream in,OutputStream out) throws IOException{ 556 lastReadTime = System.currentTimeMillis(); 557 byte[] buf = new byte[BUF_SIZE]; 558 int len = 0; 559 while(len >= 0){ 560 try{ 561 if(len!=0){ 562 out.write(buf,0,len); 563 out.flush(); 564 } 565 len= in.read(buf); 566 lastReadTime = System.currentTimeMillis(); 567 }catch(InterruptedIOException iioe){ 568 if(iddleTimeout == 0) return; long timeSinceRead = System.currentTimeMillis() - lastReadTime; 570 if(timeSinceRead >= iddleTimeout - 1000) return; 572 len = 0; 573 574 } 575 } 576 } 577 static final String command_names[] = {"CONNECT","BIND","UDP_ASSOCIATE"}; 578 579 static final String command2String(int cmd){ 580 if(cmd > 0 && cmd < 4) return command_names[cmd-1]; 581 else return "Unknown Command "+cmd; 582 } 583 } 584 | Popular Tags |