📄 proxyloginhandler.java
字号:
private void parseSocks4Reply( ByteBuffer reply ) throws IOException {
byte ver = reply.get();
byte resp = reply.get();
if( ver != 0 || resp != 90 ) {
throw new IOException( "SOCKS 4(a): connection declined [" +ver+ "/" + resp + "]" );
}
}
private void sendMessage( ByteBuffer msg ) throws IOException {
long start_time = SystemTime.getCurrentTime();
while( msg.hasRemaining() ) {
if( proxy_connection.write( new ByteBuffer[]{ msg }, 0, 1 ) < 1 ) {
if( SystemTime.getCurrentTime() - start_time > 30*1000 ) {
String error = "proxy handshake message send timed out after 30sec";
Debug.out( error );
throw new IOException( error );
}
try { Thread.sleep( 10 ); }catch( Throwable t ) {t.printStackTrace();}
}
}
}
private int readMessage( ByteBuffer msg ) throws IOException {
if( read_start_time == 0 ) read_start_time = SystemTime.getCurrentTime();
long bytes_read = proxy_connection.read( new ByteBuffer[]{ msg }, 0, 1 );
if( !msg.hasRemaining() ) {
msg.position( 0 );
read_start_time = 0; //reset for next round
return READ_DONE;
}
if( SystemTime.getCurrentTime() - read_start_time > 30*1000 ) {
String error = "proxy message read timed out after 30sec";
Debug.out( error );
throw new IOException( error );
}
return( bytes_read==0?READ_NO_PROGRESS:READ_NOT_DONE);
}
private ByteBuffer[] createSocks4Message() throws Exception {
ByteBuffer handshake = ByteBuffer.allocate( 256 + mapped_ip.length() ); //TODO convert to direct?
handshake.put( (byte)4 ); // socks 4(a)
handshake.put( (byte)1 ); // command = CONNECT
handshake.putShort( (short)remote_address.getPort() );
byte[] ip_bytes = HostNameToIPResolver.syncResolve( remote_address.getAddress().getHostAddress() ).getAddress();
handshake.put( ip_bytes[ 0 ] );
handshake.put( ip_bytes[ 1 ] );
handshake.put( ip_bytes[ 2 ] );
handshake.put( ip_bytes[ 3 ] );
if( socks_user.length() > 0 ) {
handshake.put( socks_user.getBytes() );
}
handshake.put( (byte)0 );
handshake.flip();
return new ByteBuffer[] { handshake, ByteBuffer.allocate( 8 ) }; //TODO convert to direct?
}
private ByteBuffer[] createSocks4aMessage() {
ByteBuffer handshake = ByteBuffer.allocate( 256 + mapped_ip.length() ); //TODO convert to direct?
handshake.put( (byte)4 ); // socks 4(a)
handshake.put( (byte)1 ); // command = CONNECT
handshake.putShort( (short)remote_address.getPort() ); // port
handshake.put( (byte)0 );
handshake.put( (byte)0 );
handshake.put( (byte)0 );
handshake.put( (byte)1 ); // indicates socks 4a
if( socks_user.length() > 0 ) {
handshake.put( socks_user.getBytes() );
}
handshake.put( (byte)0 );
handshake.put( mapped_ip.getBytes() );
handshake.put( (byte)0 );
handshake.flip();
return new ByteBuffer[] { handshake, ByteBuffer.allocate( 8 ) }; //TODO convert to direct?
}
private ByteBuffer[] createSocks5Message() {
ByteBuffer handshake = ByteBuffer.allocate( 256 + mapped_ip.length() ); //TODO convert to direct?
if( socks5_handshake_phase == 0 ) { // say hello
//System.out.println( "socks5 write phase 0" );
handshake.put( (byte)5 ); // socks 5
handshake.put( (byte)2 ); // 2 methods
handshake.put( (byte)0 ); // no auth
handshake.put( (byte)2 ); // user/pw
handshake.flip();
socks5_handshake_phase = 1;
return new ByteBuffer[] { handshake, ByteBuffer.allocate( 2 ) }; //TODO convert to direct?
}
if( socks5_handshake_phase == 1 ) { // user/password auth
//System.out.println( "socks5 write phase 1" );
handshake.put( (byte)1 ); // user/pw version
handshake.put( (byte)socks_user.length() ); // user length
handshake.put( socks_user.getBytes() );
handshake.put( (byte)socks_password.length() ); // password length
handshake.put( socks_password.getBytes() );
handshake.flip();
socks5_handshake_phase = 2;
return new ByteBuffer[] { handshake, ByteBuffer.allocate( 2 ) }; //TODO convert to direct?
}
if( socks5_handshake_phase == 2 ) { // request
//System.out.println( "socks5 write phase 2" );
handshake.put( (byte)5 ); // version
handshake.put( (byte)1 ); // connect
handshake.put( (byte)0 ); // reserved
// use the maped ip for dns resolution so we don't leak the
// actual address if this is a secure one (e.g. I2P one)
try {
byte[] ip_bytes = HostNameToIPResolver.syncResolve( mapped_ip ).getAddress();
handshake.put( (byte)1 ); // IP4
handshake.put( ip_bytes[ 0 ] );
handshake.put( ip_bytes[ 1 ] );
handshake.put( ip_bytes[ 2 ] );
handshake.put( ip_bytes[ 3 ] );
}
catch (Throwable e) {
handshake.put( (byte)3 ); // address type = domain name
handshake.put( (byte)mapped_ip.length() ); // address type = domain name
handshake.put( mapped_ip.getBytes() );
}
handshake.putShort( (short)remote_address.getPort() ); // port
handshake.flip();
socks5_handshake_phase = 3;
return new ByteBuffer[] { handshake, ByteBuffer.allocate( 5 ) }; //TODO convert to direct?
}
//System.out.println( "socks5 write phase 3..." );
//reply has to be processed in two parts as it has variable length component at the end
//socks5_handshake_phase == 3, part two
socks5_handshake_phase = 4;
return new ByteBuffer[] { null, ByteBuffer.allocate( socks5_address_length ) }; //TODO convert to direct?
}
private boolean parseSocks5Reply( ByteBuffer reply ) throws IOException {
if( socks5_handshake_phase == 1 ) { // reply from hello
//System.out.println( "socks5 read phase 1" );
reply.get(); // version byte
byte method = reply.get();
if( method != 0 && method != 2 ) {
throw new IOException( "SOCKS 5: no valid method [" + method + "]" );
}
// no auth -> go to request phase
if( method == 0 ) {
socks5_handshake_phase = 2;
}
return false;
}
if( socks5_handshake_phase == 2 ) { // reply from auth
//System.out.println( "socks5 read phase 2" );
reply.get(); // version byte
byte status = reply.get();
if( status != 0 ) {
throw new IOException( "SOCKS 5: authentication fails [status=" +status+ "]" );
}
return false;
}
if( socks5_handshake_phase == 3 ) { // reply from request, first part
//System.out.println( "socks5 read phase 3" );
reply.get(); // version byte
byte rep = reply.get();
if( rep != 0 ) {
String error_msgs[] = {
"",
"General SOCKS server failure",
"connection not allowed by ruleset",
"Network unreachable",
"Host unreachable",
"Connection refused",
"TTL expired",
"Command not supported",
"Address type not supported" };
String error_msg = rep < error_msgs.length ? error_msgs[ rep ] : "Unknown error";
throw new IOException( "SOCKS request failure [" + error_msg + "/" + rep + "]" );
}
reply.get(); // reserved byte
byte atype = reply.get();
byte first_address_byte = reply.get();
if( atype == 1 ) {
socks5_address_length = 3; // already read one
}
else if( atype == 3 ) {
socks5_address_length = first_address_byte; // domain name, first byte gives length of remainder
}
else {
socks5_address_length = 15; // already read one
}
socks5_address_length += 2; // 2 bytes for port
return false;
}
//System.out.println( "socks5 read phase 4..." );
//socks5_handshake_phase 4
//reply from request, last part
return true; //only done AFTER last part of request reply has been read from stream
}
public interface ProxyListener {
/**
* The proxied connection attempt succeeded.
*/
public void connectSuccess() ;
/**
* The proxied connection attempt failed.
* @param failure_msg failure reason
*/
public void connectFailure( Throwable failure_msg );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -