2015-11-29 15:31:51 +00:00
|
|
|
package eu.siacs.conversations.utils;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.OutputStream;
|
|
|
|
import java.net.InetAddress;
|
|
|
|
import java.net.InetSocketAddress;
|
|
|
|
import java.net.Socket;
|
|
|
|
import java.nio.ByteBuffer;
|
|
|
|
|
|
|
|
import eu.siacs.conversations.Config;
|
|
|
|
|
|
|
|
public class SocksSocketFactory {
|
|
|
|
|
2016-09-27 09:44:50 +00:00
|
|
|
private static final byte[] LOCALHOST = new byte[]{127,0,0,1};
|
|
|
|
|
2019-10-07 20:02:36 +00:00
|
|
|
public static void createSocksConnection(final Socket socket, final String destination, final int port) throws IOException {
|
2019-10-03 07:37:01 +00:00
|
|
|
final InputStream proxyIs = socket.getInputStream();
|
|
|
|
final OutputStream proxyOs = socket.getOutputStream();
|
2015-11-29 15:31:51 +00:00
|
|
|
proxyOs.write(new byte[]{0x05, 0x01, 0x00});
|
2019-10-07 20:02:36 +00:00
|
|
|
proxyOs.flush();
|
|
|
|
final byte[] handshake = new byte[2];
|
|
|
|
proxyIs.read(handshake);
|
|
|
|
if (handshake[0] != 0x05 || handshake[1] != 0x00) {
|
2019-09-05 10:08:58 +00:00
|
|
|
throw new SocksConnectionException("Socks 5 handshake failed");
|
2019-09-01 13:06:59 +00:00
|
|
|
}
|
2019-10-07 20:02:36 +00:00
|
|
|
final byte[] dest = destination.getBytes();
|
2019-10-03 07:37:01 +00:00
|
|
|
final ByteBuffer request = ByteBuffer.allocate(7 + dest.length);
|
2015-11-29 15:31:51 +00:00
|
|
|
request.put(new byte[]{0x05, 0x01, 0x00, 0x03});
|
|
|
|
request.put((byte) dest.length);
|
|
|
|
request.put(dest);
|
|
|
|
request.putShort((short) port);
|
|
|
|
proxyOs.write(request.array());
|
2019-10-07 20:02:36 +00:00
|
|
|
proxyOs.flush();
|
|
|
|
final byte[] response = new byte[7 + dest.length];
|
2015-11-29 15:31:51 +00:00
|
|
|
proxyIs.read(response);
|
|
|
|
if (response[1] != 0x00) {
|
2019-09-05 10:08:58 +00:00
|
|
|
if (response[1] == 0x04) {
|
|
|
|
throw new HostNotFoundException("Host unreachable");
|
|
|
|
}
|
|
|
|
if (response[1] == 0x05) {
|
|
|
|
throw new HostNotFoundException("Connection refused");
|
|
|
|
}
|
|
|
|
throw new SocksConnectionException("Unable to connect to destination "+(int) (response[1]));
|
2015-11-29 15:31:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-01 13:06:59 +00:00
|
|
|
public static boolean contains(byte needle, byte[] haystack) {
|
|
|
|
for(byte hay : haystack) {
|
|
|
|
if (hay == needle) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-10-03 18:47:28 +00:00
|
|
|
private static Socket createSocket(InetSocketAddress address, String destination, int port) throws IOException {
|
2015-11-29 15:31:51 +00:00
|
|
|
Socket socket = new Socket();
|
2015-11-30 15:01:48 +00:00
|
|
|
try {
|
|
|
|
socket.connect(address, Config.CONNECT_TIMEOUT * 1000);
|
|
|
|
} catch (IOException e) {
|
|
|
|
throw new SocksProxyNotFoundException();
|
|
|
|
}
|
2015-11-29 15:31:51 +00:00
|
|
|
createSocksConnection(socket, destination, port);
|
|
|
|
return socket;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Socket createSocketOverTor(String destination, int port) throws IOException {
|
2016-09-27 09:44:50 +00:00
|
|
|
return createSocket(new InetSocketAddress(InetAddress.getByAddress(LOCALHOST), 9050), destination, port);
|
2015-11-29 15:31:51 +00:00
|
|
|
}
|
|
|
|
|
2019-09-05 10:08:58 +00:00
|
|
|
private static class SocksConnectionException extends IOException {
|
|
|
|
SocksConnectionException(String message) {
|
|
|
|
super(message);
|
|
|
|
}
|
2015-11-29 15:31:51 +00:00
|
|
|
}
|
2015-11-30 15:01:48 +00:00
|
|
|
|
|
|
|
public static class SocksProxyNotFoundException extends IOException {
|
|
|
|
|
|
|
|
}
|
2019-09-05 10:08:58 +00:00
|
|
|
|
|
|
|
public static class HostNotFoundException extends SocksConnectionException {
|
|
|
|
HostNotFoundException(String message) {
|
|
|
|
super(message);
|
|
|
|
}
|
|
|
|
}
|
2015-11-29 15:31:51 +00:00
|
|
|
}
|