I have couple of questions about the UDP requests in SOCKS5. I've already read this paper https://www.rfc-editor.org/rfc/rfc1928#section-7 and i'm trying to implement it in C++.
Questions:
Do i need to use the "UDP request header" in both sending and receiving?
Can i use something like "WSASendTo" from winsock2 to redirect packets trough the SOCKS5 server?
Do i need to use the "UDP request header" in both sending and receiving?
Yes. This is covered in the document section you linked to:
A UDP-based client MUST send its datagrams to the UDP relay server at the UDP port indicated by BND.PORT in the reply to the UDP ASSOCIATE request. If the selected authentication method provides encapsulation for the purposes of authenticity, integrity, and/or confidentiality, the datagram MUST be encapsulated using the appropriate encapsulation. Each UDP datagram carries a UDP request header with it:
...
When a UDP relay server decides to relay a UDP datagram, it does so silently, without any notification to the requesting client. Similarly, it will drop datagrams it cannot or will not relay. When a UDP relay server receives a reply datagram from a remote host, it MUST encapsulate that datagram using the above UDP request header, and any authentication-method-dependent encapsulation.
That means that both UDP datagrams sent by you to the SOCKS relay, and UDP datagrams you receive from the SOCKS relay, carry the same header.
Can i use something like "WSASendTo" from winsock2 to redirect packets trough the SOCKS5 server?
You can use WSASendTo() to send your own datagrams to the SOCKS relay, yes.
But, if by redirect you mean to make other applications' UDP sockets send/receive datagarms through the SOCKS relay without their knowledge, then no.
I'm trying to use SOCKS v5 proxy with TIdUDPClient. I'm using C++ Builder 10.3 in Windows x64.
Here is my code so far:
TIdSocksInfo* socksInfo = new TIdSocksInfo();
socksInfo->Host = "ip address of the proxy server";
socksInfo->Port = proxyPort;
socksInfo->Version = svSocks5;
socksInfo->Authentication = saNoAuthentication;
IdUDPClient1->Host = "ip address of my udp server";
IdUDPClient1->Port = port;
IdUDPClient1->TransparentProxy = socksInfo;
IdUDPClient1->Connect();
I can connect to my server perfectly without the proxy.
But, it fails to connect with the proxy, so I sniffed the network with wireshark:
The UDP client sends "0.0.0.0" and 0 as the remote info, instead of sending the host and port I set in the code.
Is there anything I can do to fix this?
TIdUDPClient::Connect() will call TIdSocksInfo::OpenUDP() to send a UDP ASSOCIATION request to a SOCKS v5 proxy. TIdUDPClient passes its Host and Port property values as parameters to OpenUDP().
However, TIdSocksInfo::OpenUDP() ignores these Host and Port values that are passed to it. It is hard-coded to send IP 0.0.0.0 (or ::0 for IPv6) and port 0 to the SOCKS proxy. And this is OK, per the SOCKS v5 spec, RFC 1928:
UDP ASSOCIATE
The UDP ASSOCIATE request is used to establish an association within the UDP relay process to handle UDP datagrams. The DST.ADDR and DST.PORT fields contain the address and port that the client expects to use to send UDP datagrams on for the association. The server MAY use this information to limit access to the association. If the client is not in possesion of the information at the time of the UDP ASSOCIATE, the client MUST use a port number and address of all zeros.
A UDP association terminates when the TCP connection that the UDP ASSOCIATE request arrived on terminates.
In the reply to a UDP ASSOCIATE request, the BND.PORT and BND.ADDR fields indicate the port number/address where the client MUST send UDP request messages to be relayed.
So, in a UDP ASSOCIATION request, the specified Host/Port is the local Host/Port that the client will send outgoing datagrams from, or zeros if it does not know that info yet. This lets the proxy's UDP relay know where datagrams will come from when datagrams are being sent from the client to a target peer, and where to send datagrams to when datagrams are being sent from a target peer to the client. If the requested Host/Port is all zeros, the relay should simply use the Host/Port that sent the request.
The Host/Port specified in a UDP ASSOCIATION request is NOT the target peer Host/Port that datagrams are to be forwarded to, like you are thinking. That target info is specified in the individual datagrams that the client will pass to the proxy for forwarding AFTER the association is created. Unlike TCP, UDP is connection-less, so a client can create a single association and then send datagrams to multiple targets, if it wants to.
There is no connection in UDP, so there is nothing for the proxy to send to the target server while processing a UDP ASSOCIATION request. It is simply setting up the proxy's listening port that will then relay subsequent datagrams between the client and the target server.
When sending datagrams for forwarding afterwards, TIdUDPClient::SendBuffer() will call TIdSocksInfo::SendToUDP(), which is also passed the TIdUDPClient's Host and Port property values. SendUDP() will then send a datagram with that target info to the proxy's relay port:
A UDP-based client MUST send its datagrams to the UDP relay server at the UDP port indicated by BND.PORT in the reply to the UDP ASSOCIATE request. If the selected authentication method provides encapsulation for the purposes of authenticity, integrity, and/or confidentiality, the datagram MUST be encapsulated using the appropriate encapsulation. Each UDP datagram carries a UDP request header with it:
... [request header, containing DST.ADDR and DST.PORT in it] ...
When a UDP relay server decides to relay a UDP datagram, it does so silently, without any notification to the requesting client. Similarly, it will drop datagrams it cannot or will not relay. When a UDP relay server receives a reply datagram from a remote host, it MUST encapsulate that datagram using the above UDP request header, and any authentication-method-dependent encapsulation.
The UDP relay server MUST acquire from the SOCKS server the expected IP address of the client that will send datagrams to the BND.PORT given in the reply to UDP ASSOCIATE. It MUST drop any datagrams arriving from any source IP address other than the one recorded for the particular association.
...
So, whatever problem you are having with communicating with your target server, it is likely not related to TIdUDPClient1::Connect() at all, it is more likely related to TIdUDPClient::SendBuffer() and TIdUDPClient::ReceiveBuffer() instead. Either:
the proxy's UDP relay is ignoring the datagrams that TIdUDPClient is requesting be forwarded to the target server, or it is ignoring the server's replies.
datagrams are getting lost in flight on their way to the target server, or on their way back to the proxy.
If you sniff TIdUDPClient's traffic again and see your actual communication datagrams targeting your server properly, then you are going to have to sniff the traffic on the other side of the proxy to make sure those datagrams are actually being forwarded onward. If they are, then the problem has to be on the network or the server itself. If they are not, then the problem has to be on the proxy itself.
I am using boost::asio, TCP communication and C++ to create a client and a server that talk over a TCP socket. I need both the client and the server to be able send and receive data to each other. I am able to make them communicate over a socket where the server is continuously sending some data and the client is continuously reading on the socket. It works.
Now for the other way communication : For client to send some data and the server to be able to read it, can I use the same socket for this? Or Do I need to use a separate socket? Is it possible to read and write on the same socket for two applications communicating over TCP?
A boost::asio based example to illustrate this will be great if available. But I am able to find examples which are about only one-way communications.
For client to send some data & server to be able to read it, can I use the same socket for this? Or Do I need to use a separate socket ? Is it possible to read and write on the same socket for two applications communicating over TCP ?
Yes. TCP is full duplex. Applications define the protocol of what/how messages are exchanged between client and server. Weather they do asynchronously or synchronously, TCP doesn't care.
The client server paradigm in tcp is one where the client initiates the connection and the server listens for incoming connections. Once tge connection is established, it is up to higher layer protocol like http to establish how data is exchanged. As far as tcp is concerned both client and server may send or receive data any way they choose. Tcp is full duplex.
I know that SOCKS 5 supports UDP and I have been over the structure of the packets that are sent/received in negotiating with a SOCKS proxy.
The one thing I am not clear on is the procedure for setting up to register with a proxy to send/receive UDP packets.
Specifically, my biggest question is, "Is the connection to the SOCKS proxy that is used to negotiate a UDP associate relationship still made with TCP/IP?". In other words, "Do you end up using a TCP/IP socket to receive UDP packets routed through a SOCKS proxy?"
I would imagine that, if you used a TCP/IP connection to establish a pathway for UDP communication, you'd kind of be missing the whole point of establishing UDP communications. However, on the other hand, if the negotiation were made using UDP (and resulted in a UDP socket), then how would the relationship be terminated when your application is shutting down and no longer needs the proxy to "remember" you?
I have been all over the net looking for an example...but can't find anything. Any help (especially an example) would be appreciated.
https://www.rfc-editor.org/rfc/rfc1928
"A UDP-based client MUST send its datagrams to the UDP relay server at
the UDP port indicated by BND.PORT in the reply to the UDP ASSOCIATE
request"
but
"UDP association terminates when the TCP connection that the UDP
ASSOCIATE request arrived on terminates."
I actually tried using it once, but failed, because many "socks5" proxy
implementations don't actually support the complete protocol.
So I'd suggest to set up a working test case first (find an app which
would support socks5 udp proxy, and a proxy where it would actually work).
Then any network sniffer would tell you how it really works (if it does).
I have a requirement to send some 100 bytes data over internet .My machine is connected to internet.
I can do this with HTTP by sending requests and receiving responses.
But my requirement is just to send data not receive response.
I am thinking of doing this using UDP Client server program. But to do that I need to host UDP client on internet?
Is there any other way to do that?
any suggestions?
Cheap answer to send 100 bytes of data on the internet.
C:\Windows\system32>ping -n 1 -l 100 -4 google.com
Pinging google.com [209.85.171.99] with 100 bytes of data:
Reply from 209.85.171.99: bytes=56 (sent 100) time=174ms TTL=233
Ping statistics for 209.85.171.99:
Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 174ms, Maximum = 174ms, Average = 174ms
Anything that happens on the internet requires a client and a server.
One box is in the role of client, the other is in the role of server for your specific transaction.
Usually (but not always) your local box is a client and some other box is the server.
Software MUST be running on both to implement some protocol for exchanging data.
A server can listen on TCP or UDP sockets, with some restrictions. Some port numbers are privileged. Some port numbers are blocked by firewalls.
Port 80, while rarely blocked by firewalls is a privileged port. Generally, you need a web server (e.g., Apache) or privileges to listen on port 80.
"Sending 100 bytes" can be done using a lot of available protocols: Echo, Telnet, FTP, HTTP to name a few.
The big advantage of HTTP is that port 80 is very often open. With other protocols you have to rely on the operators to open the port.
In order to send data but not receive a response, you can simply write your program in such a way that it does not listen for a response. This doesn't mean one won't be sent to you, just that you won't get it.
For example, you can make sure you don't call "recv" on the socket. Also, you can use "shutdown" to disable reads on the socket. Depending on the underlying implementation, going the "shutdown" route might cause all incoming packets to simply be dropped.
As far as how to send the packets, really any sort of protocol will work. Of course, you need to know of a destination server on the Internet, but you've got plenty of options. Perhaps the simplest route to take is what you have suggested: HTTP (perhaps use www.google.com as your destination server).
You need a client (you) and a server (other end). For UDP, you send datagrams over the Internet (using IP). UDP doesn't provide the safety that TCP does, but doesn't require a response (but such responses are part of their protocols, not yours).
I would suggest using TCP to save you some headache.
Also, make sure you're not behind a firewall, else your packets won't make it to their destination as you'd expect.
Hmmm...
You want to send short messages over the internet, but without any response.
Your application wouldn't by any chance be some kind of spyware, would it?
Use UDP. Open a socket, send the data, close the socket. That's it. Here is a Python version of the client:
import socket
data = 100*'x'
address = ('192.168.0.123', 8080) # Host, port
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.connect(address)
sock.send(data)
sock.close()
On the Wikipedia page about UDP there is some corresponding WinSock code.
Of course the other side must be reachable, and there must be someone listening there, otherwise the target machine will reply with an ICMP "port unreachable" packet (at least if it complies with standards).
If you want a UDP listener on the internet, it will have to be hosted somewhere.
You can get HTTP hosting much easier, it's everywhere, UDP you may need your own machine or at least a VM.
curl is a command line tool for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, Telnet and TFTP. curl supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, cookies, user+password authentication (Basic, Digest, NTLM, Negotiate, kerberos...), file transfer resume, proxy tunneling and a busload of other useful tricks.
See examples here