ould you kindly elaborate on your point about
allowing any proxy along the way to figure out the full route and the final destination
?
My understanding was that each subsequent proxy is only aware of the source of its immediate predecessor and its next destination. |
If you use a single proxy, it unavoidable needs to know the actual source IP address and the actual destination IP address.
Encrypting the payload, e.g. with HTTPS, doesn't change anything about this.
By
chaining multiple proxies, each proxy in the chain
ideally only knows its immediate predecessor and its immediate successor.
(Only the "entry" and "exit" nodes need to know the actual source and destination IP address, respectively)
https://miro.medium.com/v2/resize:fit:720/format:webp/1*j2aTFBQTd9e1PlFDjeKw1g.jpeg
But: In general, there is absolutely
nothing that prevents an "evil" proxy to look at the
nested packets/data and figure out the full route!
Again, encrypting only the payload (innermost packet/layer), e.g. with HTTPS, doesn't change anything about this.
That is why "onion routing", e.g. Tor, uses
multiple layers of encryption, so that each proxy along the chain can
only remove the "outermost" (at this point of the chain) layer of encryption, in order to figure out the
next node, but can
not decrypt the nested data any further.
https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Onion_diagram.svg/1024px-Onion_diagram.svg.png
HTTPS is still used (usually), but only at the "innermost" layer that goes to the final destination server.
To my understanding, SOCKS5 does
not use any form of encryption, even though it can pass trough an encrypted stream (e.g HTTPS). This means that when you extend the chain from the first SOCKS proxy to the second one, then the first proxy can "see" (as plain text!) the SOCKS packet/header that is to be passed to the second proxy. Hence, the first proxy learns the IP address of the final destination 😱
1 2 3 4
|
// Here you should check the proxy's response status
char proxyResponse[2000];
recv(ConnectSocket, proxyResponse, 2000, 0);
puts(proxyResponse);
|
|
Be aware that, as far as
SOCK_STREAM
(TCP/IP) is concerned, a single call to
recv()
is
not guaranteed to give you the full response packet/message! Instead,
recv()
reads up to
n bytes from the stream, but
fewer bytes may be read – which may very well be an "incomplete" packet/message. There also is absolutely
no guarantee that
recv()
will stop reading right after the SOCKS response.
TCP/IP is a contiguous streams of bytes. Therefore, message boundaries have to be implemented in higher level protocols.
In general, you have to call
recv()
in a
loop, until the expected number of bytes have been received/accumulated. If the length of the message is
not fixed (known beforehand), you have to keep on reading until the "end of message" indicator has been received. For example, in HTTP the end of the "header" is indicated by
\r\n\r\n
, and the length of the "body" is limited by the
Content-Length:
header field.
Anyway, if
recv()
returns
more bytes than expected (for the current packet/message), you
must not simply ignore/discard those bytes, because they probably belong to whatever packet/message comes next in the TCP/IP stream...
https://stackoverflow.com/a/41383398