/*******************************************************************************
* gMix open source project - https://svs.informatik.uni-hamburg.de/gmix/
* Copyright (C) 2014 SVS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package userGeneratedContent.testbedPlugIns.layerPlugIns.layer5application.socks_v0_001.socks;
import java.io.IOException;
import java.io.InputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import staticContent.framework.util.Util;
import userGeneratedContent.testbedPlugIns.layerPlugIns.layer5application.socks_v0_001.Config;
/**
* Forwards DatagramPackets to webserver.
* Reads a DatagramPacket from client with SOCKS5 UDP Relay Header.
* Deletes the header and forms a UDP Packet with the destination ip and port included in this header.
*
* @author Haseloff, Schmitz, Sprotte
*
*/
public class ForwarderSocks5UDPtoWebserver extends Thread
{
InputStream fromClient;
DatagramSocket fromToWebserver;
Config config;
public ForwarderSocks5UDPtoWebserver(InputStream fromClient, DatagramSocket fromToWebserver, Config config)
{
this.fromClient = fromClient;
this.fromToWebserver = fromToWebserver;
this.config = config;
start();
}
/**
* Reads a couple of bytes depending on the address type.
*
* @param aTyp valid values: 0x01, 0x03, 0x04
* @return InetAddress
*/
private InetAddress getInetAddress(byte aTyp)
{
byte[] byteAddress = null;
int length;
InetAddress address = null;
try
{
switch (aTyp)
{
case 0x01: // IP v4
length = 4;
byteAddress = Util.forceRead(fromClient, length);
address = InetAddress.getByAddress(byteAddress);
break;
case 0x03: // Domain, first byte defines the length of it
length = Util.unsignedByteToShort((byte) fromClient.read());
byteAddress = Util.forceRead(fromClient, length);
String stringAddress = Util.getStringWithoutNewLines(byteAddress);
address = InetAddress.getByName(stringAddress);
break;
case 0x04: // IP v6
length = 16;
byteAddress = Util.forceRead(fromClient, length);
address = InetAddress.getByAddress(byteAddress);
break;
default:
//this.sendSocks5FailReply((byte) 0x05, (byte) 0x08, (byte) 0x00); // reply 0x08: Address type not supported
System.out.println("UDPForwarder: i do only support IP V4, Domains or IP V6 addresses");
//System.out.println("UDPForwarder: Sent CONNECT reply: 0x08");
//close();
}
} catch (UnknownHostException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return address;
}
/**
* Forms an UDP Packet and sends it to webserver.
*
* @param destIP destination ip, exracted from the header
* @param destPort destination port, exracted from the header
* @param payload
*/
private void sendUDPPayloadToWebserver(InetAddress destIP, int destPort, byte[] payload)
{
DatagramPacket packet = new DatagramPacket(payload, payload.length, destIP, destPort);
try
{
fromToWebserver.send(packet);
} catch (IOException e)
{
e.printStackTrace();
}
}
public void run()
{
while (true)
{
/* Receive UDP Request Header and UDP payload from Client *Step 8* */
try
{
/*byte[] UDPReserved = */Util.forceRead(fromClient, 2);
/*byte fragment = (byte) */fromClient.read();
byte aTyp = (byte) fromClient.read();
InetAddress destIP = getInetAddress(aTyp);
byte[] destbPort = Util.forceRead(fromClient, 2); // read DST.PORT
int destPort = Util.unsignedShortToInt(destbPort);
//byte[] payload = Util.forceRead(fromClient, 24); // TODO: flexible payload, read until 2 zero bytes
System.out.println("UDPForwarder: " + fromClient.available());
byte[] payload = Helper.forceReadUntilNzeroBytesOrEnd(fromClient, Config.N_ZERO_BYTES);
if (config.TALK_A_LOT == true)
{
System.out.println("UDPForwarder: read UDP Request Header from Client");
}
// Send UDP Payload to Webserver
this.sendUDPPayloadToWebserver(destIP, destPort, payload);
} catch (IOException e)
{
e.printStackTrace();
}
}
}
}