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.
Related
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.
My friend and I are writing a game in sfml. We wrote both the client and the server in C++. The library we used to handle the networking is SFML. The clients send block update packets to the server and the server sends them to all connected players. This works fine, both my friend and I are able to receive the TCP packets. The problem is with the UDP player position packets. The server receives a UDP packet containing the players x y z (position coordinates) and pitch and yaw(direction the player is looking). Then it sends that information to all other connected clients.(This happens 10 times per second) We put a simple printf() statement to detect whether my friend is even receiving the udp packets but it turns out he was not. And I am obviously receiving the UDP packets since it I am able to see his position.
We thought this was because the server is sending UDP packets to the clients' router's IP but the packet does not contain the local ip of the computer the packet is meant for. Later, we learned that when the server sends a packet to the router, the packet gets sent containing a public ip address and a public port, the router then maps that port to a local ip address and a local port. However this is called port forwarding and requires the routers to be configured.
We just want to know why isn't this a problem with TCP connections?
Why am I able to receive the UDP packets without port forwarding?
Is port forwarding necessary for UDP communication?
We just want to know why isn't this a problem with TCP connections?
Because a connection is bidirectional.
Why am I able to receive the UDP packets without port forwarding?
There could be a lot of possibilities and there's no way we can know without looking much more closely. Here are a few possibilities:
You aren't behind a router that's doing NAT.
The router that does NAT for you isn't between your client and the server.
Your client sent a UDP datagram to the server and your router recognizes the response UDP datagram as a reply to that, creating the effect of having a "UDP connection".
Your client uses UPnP and your router supports UPnP to get port forwarding without special effort.
The server sets the source and destination UDP ports incorrectly and, by luck, it still works in your case. For example, the source and destination ports might happen to be the same or your router's NAT is especially permissive.
The server sets its source IP address incorrectly and this just happens to work in your case either because your router's NAT is more permissive or because the IP address you send to and the IP address the server sends from happen to be the same in your case.
You send a UDP datagram to the server and your friend didn't, thus your datagrams are seen as replies and your friend's aren't.
You can narrow things down if you can dump packets at the server. Seeing a UDP datagram from your friend as seen by the server followed by a UDP datagram from the server to your friend would help narrow things down a lot.
Is port forwarding necessary for UDP communication?
Generally no. If the client sends the first UDP datagram and the server correctly swaps the source and destination ports and the source and destination IP addresses, the UDP reply datagram will usually work.
The client must send UDP to the server first. The server must ensure that the UDP datagram is seen as a reply. That means the server looks at the UDP datagrams it gets from the client and ensures that it responds from the port the client sent UDP to and to the port the client sent UDP from. Similarly, it must send to the IP address the client sent from and send from the IP address the client send to.
Generally, servers offer TCP fallback or some other form of NAT penetration in case things don't "just work".
I have a multicast server which multicast on an IP 233.1.2.8 on some ports
I need to connect to that server directly using its actual IP do not want to use the broadcast. I want to get actual data it sends on a specific port let say
Multicast Ip 233.1.2.8 port 32334 and 35245
Actual IP 198.122.55.191 port 35366
so i want to read the data of 35366
I can see that data in CommView.exe but can not read it if i try to connect it connects but no data
Thanks
You may want to rethink your question. IP packets have a source and destination address and port, so lets summarise:
You are looking for multicast packets with source port 35366.
Multicast address 233.1.2.8.
Destination port 32334 or 32335.
You will have to open two sockets, one listening to port 32334 and one to 32335, for each socket you will have to the multicast address 233.1.2.8. That gets you a stream of packets from any host, now you have a choice:
Use connect() to restrict to packets from 198.122.55.191.
Use recvmsg() or recvfrom() to read each packet with the source IP address and filter the stream within your application.
Use Source-Specific-Multicast (SSM) and subscribe to multicast address 233.1.2.8 from 198.122.55.191.
The last option usually requires IGMPv3 enabled network and is limited to 232.0.0.0/8 addresses.
Multicast by definition is one-way street: the server sends data to a group, and you subscribe to it.
Connecting to a server cannot be done through UDP, it requires a TCP server actually being there and listening for incoming connections on that particular port. The fact that that port is used for sending out multicast packets doesn't suggest that there's anyone listening on it as well.
If you want to read the data sent from a particular port - then you need to subscribe to all the groups, and analyze the UDP packets (and the IP frame if you have several servers transmitting, to know the origin IP) to see where they're coming from, and filter out the ones that come from the origin you fancy.
You can have a look at this site. It has an example also
http://tack.ch/multicast/
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 am writing simple client-server program.
Client send some messages to server using UDP or TCP. Server must be able to support both UDP and TCP.
If client, sends message using UDP, sequence of method calls in client is socket(),bind(),sendto(),recvfrom(),close() and that in server is socket(),bind(),sendto(),recvfrom(),close().
If it uses TCP,
sequence of call in server is
socket(),bind(),listen(),accept(),send(),recv(),close().
and that in client is
socket(),bind(),connect(),send(),recv(),close()
In my program, user/client is given choice in the start to select what he want to use UDP or TCP. So, my main problem is how can I know or differentiate in the server side, if the client is sending message using TCP or UDP. If it uses TCP, I must call listen(),accept(),send(),recv()
and if it uses UDP, I don't call listen(),accept() but call sendto() and recvfrom().
So, how can I differentiate/know this in the beginning so that I can make appropriate function calls.
Thanks.
Before the packet reaches you, you don't know whether it's UDP or TCP.
So you want to bind to both UDP and TCP sockets if you expect requests both ways.
Once you did, you just know which way it came by the socket you received the packet through.
When you create the socket, you pass a type - SOCK_STREAM (TCP) or SOCK_DGRAM (UDP)
So the two kinds of traffic will be on two different sockets.
Just as Henry Troup pointed out, an IP socket is defined as
(transport, interface, port).
(UDP, 127.0.0.1, 80) is not the same IP socket as (TCP, 127.0.0.1, 80) , thus you can safely bind to both of them and listen for incoming traffic.
just let the TCP socket listen on port X, and do the UDP connections through port Y