-2

I spent more than 50 hours on this nonsense, why is my UDP implementation not working? Problem is that the server does not receive UDP packet. I made server app to log events in console and I see it's not receiving anything. Here is SOCKS5 documentation I followed: https://www.ietf.org/rfc/rfc1928.txt

byte[] response = new byte[256];
int responseLength;
Socket socket = new Socket(proxyHost, proxyPort);
DatagramSocket clientSocket = new DatagramSocket();

DataOutputStream writer = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
DataInputStream reader = new DataInputStream(new BufferedInputStream(socket.getInputStream()));

// connect/authorization request
writer.writeByte(0x05); // VER
writer.writeByte(1); // NMETHODS
writer.writeByte(0); // METHODS
writer.flush();

// connect/authorization response
responseLength = reader.read(response); // RESPONSE IS: 5 0

// udp associate request
writer.writeByte(0x05); // VER
writer.writeByte(0x03); // CMD - UDP ASSOCIATE
writer.writeByte(0x00); // RSV
writer.writeByte(0x01); // ATYP
// is what I'm sending here as DST.ADDR & DST.PORT okay?
writer.write(clientSocket.getLocalAddress().getAddress()); // DST.ADDR
writer.writeShort(clientSocket.getLocalPort()); // DST.PORT
//writer.write(InetAddress.getByName(trackerHost).getAddress());
//writer.writeShort(trackerPort);
writer.flush();

// udp associate response
reader.skipBytes(4); // skip VER, REP, RSV, ATYP bytes
relayAddress = reader.readInt();
InetAddress relayInetAddress = InetAddress.getByAddress(ByteBuffer.allocate(4).putInt(relayAddress).array());
relayPort = reader.readUnsignedShort(); // server returns some random port

// connect to relay server via datagramsocket
clientSocket.connect(relayInetAddress, relayPort);

// send package to destination server
ByteBuffer byteBuffer = ByteBuffer.allocate(16 + 10);
//header - 10 bytes
byteBuffer.putShort((short) 0); // RSV
byteBuffer.put((byte) 0); // FRAG
byteBuffer.put((byte) 1); // ATYP
byteBuffer.put(trackerInetAddress.getAddress()); // DST.ADDR
byteBuffer.putShort((short) targetPort); // DST.PORT
//packet data
byteBuffer.putLong(1);
byteBuffer.putInt(0);
byteBuffer.putInt(1);
// send packet
packet = byteBuffer.array();
DatagramPacket sendPacket = new DatagramPacket(packet, packet.length);//, relayInetAddress, relayPort);
clientSocket.send(sendPacket); // SERVER DOES NOT RECEIVE THIS

Target host is verified to be working 100% fine without proxy. Using semi-dedicated proxies from https://blazingseollc.com/proxy/ which support SOCKS5

Gintas_
  • 4,940
  • 12
  • 44
  • 87
  • Why are you reading bytes with a `Reader`? And why are you abusing both `Reader.ready()` and `InputStream.available()`? – user207421 Jun 11 '18 at 10:32
  • @EJP please elaborate more, what's wrong with that? InputStream.available() returns the amount of bytes available to read. I'm using ready() in order to wait until response packet arrives. It works on that part, I receive authentication & udp associate responses fine. The problem with reading (or more like receiving) appears only in DatagramSocket part. Of course mistake may have been made before that part. Any possible clue for solution from you is golden, so let me know – Gintas_ Jun 11 '18 at 10:45
  • 1. `Reader` reads `char`, not `byte`. 2. `while (!inputStreamReader.ready());` accomplishes exactly nothing except smoking your CPU, as the following read will block anyway. 3. There is a specific warning against using `available()` as you are doing. This is all in the Javadoc. You are also completley ignoring the content of the response; you are also assuming that there *was* a response rather than an disconnect, *and* that the response indicated success. You need to *parse* it, and to do so *as bytes*. You will find the methods of `DataInputStream` useful. Rather than all this nonsense. – user207421 Jun 11 '18 at 11:56
  • @EJP alright, I updated the code with DataInputStream & DataOutputStream; but it's not the beauty of the code that's the problem, so it did not fix anything – Gintas_ Jun 11 '18 at 12:11
  • I'm not talking about 'beauty', I'm talking about *correctness.* It is not correct to write code that disagrees with the Javadoc. I posted my remarks as a comment, not as an answer. I will now ask you why you aren't error-checking the responses. – user207421 Jun 11 '18 at 23:43

1 Answers1

0

Turns out the proxy provider does not support UDP ASSOCIATE of SOCKS5. Turns out majority of proxy providers do not support it.

Gintas_
  • 4,940
  • 12
  • 44
  • 87
  • 1
    The proxy's response has a status code in the `REP` field indicating whether the request is accepted or rejected, and if rejected then why (such as `0x07` for "command not supported"). Your code is ignoring that field (it is also ignoring the `ATYP` field and assuming the response always contains an IPv4 address, but that is not a guaratee). – Remy Lebeau Jun 11 '18 at 21:17
  • I was checking and error-checking responses of these fields in debugger, these proxy providers didn't even bother replying 0x07 or anything indicating command to be not supported – Gintas_ Jun 12 '18 at 06:14
  • they have to respond with *something*. Any value other than `0x00` in the `REP` field is a request failure. If they are just ignoring the request and not sending a response at all, then they are not compliant with the protocol. – Remy Lebeau Jun 12 '18 at 15:48
  • then they are not compliant or have misconfigured something – Gintas_ Jun 12 '18 at 17:21
  • SOCKS is very easy to implement, so I highly doubt that any proxy maker would not follow the *complete* spec, even if not all commands are implemented. I strongly suggest you use a packet sniffer, like Wireshark, to verify that you are actually transmitting the SOCKS requests correct, in the proper format, and make sure that the proxy is not actually responding at all. Maybe it is, and you are just not reading it correctly. – Remy Lebeau Jun 12 '18 at 17:57
  • I have set up my own socks5 proxy server with Dante on test VPS and verified that the code is perfectly fine. – Gintas_ Jun 13 '18 at 09:49