C# SOCKS5 Proxy Implementation doesn't always work on local computer - c#

Context
I made a SOCKS 5 Proxy implementation in C# based on the RFC 1928 specification as part of a software I'm working on. The proxy server will run locally inside my software (i.e. it's not on a remote server) and it will be used to redirect certain HTTP / HTTPS connections to a specific IP address.
How it should work / the reason for a local proxy
My software is sort of a launcher that launches a .jar file. The java program accepts optional parameters that specify a proxy server, and I want to exploit this feature to redirect any HTTP or HTTPS requests made by the java program to my own servers. This is why the proxy server MUST run on the same computer as the proxy client (the java program).
My problem
I am testing this proxy with a simple java program that tries to get a status code from a website through my proxy. For some reason, without modifying any code, approximately 8 times out of 10 the java program throws a SocketException (java.net.SocketException: Reply from SOCKS server has bad length), but at other times it works and properly prints out the HTTP response code.
What I've tried
If I run the proxy program on a separate computer or on a virtual machine, it always works without any errors (at least hopefully; I ran the java program ~20 times and it didn't throw the exception). This is not a viable solution in my case, because the proxy must run locally, as part of the program I'm working on.
My Code
The C# SOCKS implementation is too long for a SO post (~100 lines), so I have uploaded it to Pastebin.
The following is my java test code.
public static void main(String[] args) throws Exception {
Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 32128));
HttpURLConnection conn = (HttpURLConnection)(new URL("http://somedomain.com/")
.openConnection(proxy));
conn.setDoInput(true);
conn.setDoOutput(false);
conn.connect();
System.out.println(conn.getResponseCode());
}
The Question
Why does the proxy server work if I host it on a separate computer / VM, but fail when I host (and use) it locally? And when it does work locally, what could be the cause of the seemingly random behavior, and how can I fix it?
EDIT:
I forgot to mention that the code currently only functions as a transparent proxy, i.e. it doesn't relay connections to other IP addresses yet.

I just revisited this project after a 6 months break, and I have found the solution to this problem. On lines 70-73 the first four bytes of the response are sent separately with writer.Write(...). I solved the problem by replacing those four lines with a single Write call that sends an array (byte[4]) containing the four values.

Related

'No connection could be made because the target machine actively refused it'

I am working on a 'Smart Device Project' using .Net Framework 3.5. I am trying to connect to some Java SOAP services on a remote server.
In order to do that, I added 'Web References' to my project.
When I try to call my web service I get a WebException 'Unable to connect to the remote server' with the inner exception being 'No connection could be made because the target machine actively refused it'.
I searched quite a lot on the Web and StackOverflow and found a lot of ASP configuration and 'Unavaliable port' answers, but as I have another application using the exact same Service successfully, I can't get why the new one isn't getting through (It did sometimes through my tests so I suppose my client implementation isn't that bad)
I tried to look if there was some connection issue on the port by using some TcpClient:
System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient();
try
{
client.Connect("myServerName", 8087);
MessageBox.Show("Success");
} catch (Exception ex)
{
MessageBox.Show("Failure");
}
finally
{
client.Close();
}
This connection succeed.
Here is a sample on how I call my WebService:
WSServiceExtended srv = new WSServiceExtended();
srv.Proxy = new System.Net.WebProxy();
ServeurWSI wsi = new ServeurWSI();
srv.Url = "http://myServerName:8087/myServerApp/services/myService";
wsr = srv.login(wsi);
The service is called 'Extended' because I overrided the auto-generated one in order to add Cookie managment since I am using the Compact Framework. Following the sample in this thread:
https://social.msdn.microsoft.com/Forums/en-US/34d88228-0b68-4fda-a8cd-58efe6b47958/no-cookies-sessionstate-in-compact-framework?forum=vssmartdevicesvbcs
EDIT:
I made some new tests with the Web references and got it to work.
When I add the Web Reference, I have to put some Url to the Web Service. When I set it with the actual hostname instead of the 'localhost' everything is fine.
But then, since I set it manually to the real address just before the call, it shouldn't matter
srv.Url = "http://myServerName:8087/myServerApp/services/myService";
EDIT2:
I might have forgotten some specifics about my environnement.
The Web Services are exposed on my computer on some Tomcat Server.
The application I am working on is also developped on this computer (That's why I can add Web References by putting 'localhost' in the address)
The application is then deployed on a distant device (Windows CE) that will make calls the Web Services through WIFI (There, localhost wouldn't work then)
I tried calling the Web services from other computers successfully.
I'm beginning to think that there might be some differential between the called Url and the one that is set, otherwise, how would I have a difference in behaviour such as the one described in the first edit?
EDIT3:
Well..Seems like it's not a network issue but a .Net compact framework (usage?) issue...
The Url property of the Web Service implementation is simply ignored and the one in the Reference.cs is used in place.
If someone had some idea on how I could troubleshot this, I would really appreciate it.
That error means that you reached a server and the server said "no way". So you're either hitting the wrong server or the wrong port.
I find the telnet client is useful for testing stuff like this. From the command line, you can do:
telnet [servername] [port]
So something like:
telnet myServerName 8087
If it goes to a blank screen, then it connected successfully. If it does not connect, it'll tell you.
The telnet client is no longer installed by default in Windows 7+, so you'll have to install it. See here for instructions: https://technet.microsoft.com/en-ca/library/cc771275
If the connection does open, you could paste in an actual HTTP request to see what happens. A simple GET would look something like this:
GET /myServerApp/services/myService HTTP/1.1
Host: myServerName:8087
One reason for this error can be that the service binds to only a certain IP address. It could well be that the service only listens on the IP that is assigned to the host name, but not on the localhost IP (127.0.0.1).
For example:
If the host myServerName has the public IP 192.168.0.1, your service can choose to listen on all IPs assigned to the host (sometimes specifying 0.0.0.0), or it can specifically listen on 192.168.0.1 only. In that case you will not be able to connect through 127.0.0.1, because the service simply doesn't listen on that IP.
You can "use" this inverse of this feature to make a service accessible only to local clients, not on the public IP-Address, by listening on 127.0.0.1 only, but not on the public IP. This is sometimes used on Linux for example to make MySQL only accessible on the host itself.
I was starting to forget this post but I finally found the problem that was messing things up and it has nothing to do with programmation.
I was doing the calls while the device was connected to the computer via the 'Windows Mobile Device Center' allowing to access the device from Windows.
While connected, the host provided is ignored and all calls on the specified port are handled by the connected computer.
Disconnecting the device allows to communicate properly...

C#-Server / C++ Client: Socket.Accept() never finishes

I'm writing a simple C++ client that should connect to a C# server. And, while the client runs throught fine and even states it sent a bunch of bites, the C# server never gets past listener.Acceppt():
Console.WriteLine("Waiting for a connection...");
// Program is suspended while waiting for an incoming connection.
Socket handler = listener.Accept();
I took the server source from here: Microsoft MSDN: Synchronous Server Socket Example
The client code I use can be found here: Microsoft MSDN: Complete Winsock Client Code
I also checked to server with the according C# client, which worked fine. I also checked the return values of the client, which also looked pretty plausible. So I'd guess the problem lies somewhere in how C++ / C# handle the details.
I tried Wireshark to find some hints, but mysteriously there was absolutely no trace of any communication on the used port (11000).
Where should I start looking to solve this issue?
Update: All communication at the moment runs just locally. I tried my IPAddress (from ipconfig) and 127.0.0.1 for both server and client.
I just have one network adapter installed, I use that IP adress. The client checks the getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result) and returns valid information (e.g. TCP as protocol). connect() returns 0, which should be ok.
Update 2:
I tried different combinations of C++/C# Server-Client-Setups:
C++-Server, C++ Client: Works
C++-Server, C# Client: Works
C#-Server, C# Client: Works
C#-Server, C++ Client: Does not work
C#-Server, putty: Works
Update 3: I tried Wireshark on the other Server-Client constellations, but neither of them did show any traffic on tcp.port == 11000, although they did work (see Update 2). It looks like Wireshark does not show any results, because everything is just local (see Wireshark localhost traffic capture)
I had the same problem.
The connection with winsock is asynchronous. And the example in C# that you are using is synchronous.
You have to use a Asynchronous example to get communication with your C++ code.
I used this two examples!
C Sharp server
https://msdn.microsoft.com/en-us/library/fx6588te(v=vs.110).aspx
C plus plus client
https://msdn.microsoft.com/en-us/library/windows/desktop/ms737591(v=vs.85).aspx

What mechanism is used by MSYS/Cygwin to emulate Unix domain sockets?

I'm attempting to write (in C#) a piece of software that communicates with another piece of software, built with MSYS, over (MSYS emulated) Unix domain sockets. I've learned that the "socket server" (I'm not clear on what the proper terminology is) creates a temporary file with contents such as this:
!<socket >59108 282F93E1-9E2D051A-46B57EFC-64A1852F
The 59108 corresponds to a TCP port, which the "socket server" is listening on on the loopback interface. Using a packet capture tool, I've been able to determine that the "socket client" connects to this port, and information is exchanged over the loopback interface.
I replicated this behavior in my software, and the "socket client" connects to my listening port, but no information is transmitted. I believe there's another step here, one most likely involving the GUID in the "socket" file, but I've been unable to determine what it is. What do I need to do to trigger the communication from the client?
It seems that MSYS is using Cygwin's mechanism, which involves a named event, that is (probably?) created by the "server", and signaled (apparently) by the "server", but my naive attempt at an implementation doesn't seem to be working.
I've located an email written by Conrad Scott which describes various shortcomings in the "handshaking" process, and proposes a patch which allegedly solves them. In this email, Conrad describes somewhat the process used, and he indicates that there are actually TWO events, one managed by the "server" and one managed by the "client". I've used API Monitor to look for calls to CreateEvent(), and while there are several, I cannot find one that looks like the "smoking gun" here. There are no interesting calls to CreateSemaphore() either, so it seems like Conrad's patch was never applied (or, at least, it was applied some time AFTER MSYS forked Cygwin).
It appears that both the answers from divB and Mark are correct, but they both leave out some details, so this is hopefully a bit more complete.
There are 2 different implementations here. I have not done an exhaustive investigation of who implements which implementation, but as of this writing, the current version of cygwin uses the implementation described by divB and MsysGit uses the implementation described by Mark.
Initializing the server:
Create a socket (AddressFamily = IPv4, Type = Stream, Protocol = TCP). (.NET/MFC)
Bind it to loopback (127.0.0.1). (.NET/MFC)
Tell the socket to listen. (.NET/MFC)
Generate a random 16-byte GUID.
Create a file with the following contents based on the TCP port and the GUID. Using the original example where 59108 is the TCP port and 282F93E1-9E2D051A-46B57EFC-64A1852F is the GUID.
In the cygwin implementation, the socket file contents are:
!<socket >59108 s 282F93E1-9E2D051A-46B57EFC-64A1852F
And in the msysgit implementation, the socket file contents are:
!<socket >59108 282F93E1-9E2D051A-46B57EFC-64A1852F
The difference being the extra "s" between the port and the GUID.
Set the System attribute on this file.
In msysgit implementation only, Create a named wait handle with the name cygwin.local_socket.secret.58598.282F93E1-9E2D051A-46B57EFC-64A1852F (InitalState = False, Reset = AutoReset). (.NET/MFC)
58598 is derived by using a HostToNetworkOrder function on the port (as 16-bit unsigned integer). i.e. 59108 == 0xE6E4 and 58598 == 0xE4E6.
Handling connections:
Accept the incoming socket. (.NET/MFC).
In the case of the cygwin implementation only, do handshake that consists of:
Read 16 bytes. If these do not match the GUID, then fail.
Send the same 16 bytes.
Read 12 bytes as 3 32-bit integers. They are the pid, uid and gid of the calling process.
Send 12 bytes (3 32-bit integers) back. Use the pid of the server and the uid and gid that were received.
In the case of the msysgit implementation only, synchronize with the client by:
Get the port of the incoming socket. For this example, we'll say it is 63524.
Open existing wait handle for the client. (.NET/MFC). You need to convert the port to network byte order just like we did for the server. So, for this example, the name is cygwin.local_socket.secret.9464.282F93E1-9E2D051A-46B57EFC-64A1852F
Signal the server and wait for the client (ToSignal = server, WaitOn = client, Timeout = 10000 msec, ExitContext/Alertable = False). (.NET/MFC). Not 100% sure about the ExitContext/Alertable parameter, but False seems to work.
Hand off the socket to the (hopefully already existing) code for whatever it is you are doing (which in the case of all three of us, seems to be an ssh agent).
So at least for cygwin I can answer your question now: I just implemented a cygwin compatible socket server using MFC. I did it by looking into cygwin source.
It seems that there are not even events. So the patch you mentioned does not seem to have been implemented.
All that happens is:
1.) The socket file is created, the GUID ("shared key") are just random numbers.
2.) The file MUST have "system" attribute. The cygwin code does some weird permission stuff if it's on NTFS, haven't looked into that.
3.) a network socket on localhost is created with the port indicated in the socket file.
So, then, when a client connects to the socket (via TCP/IP):
4.) It first sends the 4 random numbers to the server; the server checks if they are valid
5.) The server sends them back
6.) The client sends 3 32 bit numbers: The pid, the uid and gid
7.) The server sends back his own version of these numbers.
I don't understand what's the purpose of this handshake because from a security point of view it's completely worthless.
I've worked out something that functions correctly for the build of OpenSSH (ssh-agent.exe) that comes with Git:
Setup on the server side consists of these steps:
1. Create a "secret string" that consists of four groups of eight hex digits separated by a dash ("-")
2. Listen on a local port
3. Create an EventWaitHandle with mode EventResetMode.AutoReset named cygwin.local_socket.secret.[secret string].[listen port number here with byte order reversed]
4. Write out the "socket" file, which consists of the string ![port number here, byte order NOT reversed] [secret string]
When a connection comes in, the following steps must be undertaken:
1. Open the client's event handle with EventWaitHandle.OpenExisting(), using the event name cygwin.local_socket.secret.[remote port number with byte order reversed].[secret string]
2. Signal the server's event handle and wait for the client's wait handle to be signaled with `EventWaitHandle.SignalAndWait()
I agree that it looks like the patch discussed on the mailing list was never applied. The sequence I worked out seems closer to the sequence discussed on that list, and as well, it matches the code I dug up from Cygwin.
I don't understand the disparity between what I found to work vs what divB found to work, but I did confirm that it functioned with the software I was using (Git's OpenSSH)

Why am I getting an exception (TCP error code 10061) when attempting to communicate between 2 applications using WCF?

I am trying to use WCF to setup IPC between 2 running windows applications.
I want to start out by saying that I know there are other (better?) ways to implement
this solution. But, due to some pre-existing design considerations/constraints, I'm bound to using:
- netTcpBinding
- DuplexChannelFactory<> to support bidirectional communication
All the applications, services, etc reside on the same machine as we will be
installing everything on a single dedicated piece hardware running MS Windows.
So the schematic kind of looks like this
WPFApp1
(Contains ReportingFacilityInterface definition)
Returns notifications as separate callbacks to WPFApp2
^
|
|
V
ReportingFacilityInterfaceProxy
^
|
|
V
WPFApp2 (needs to call exposed methods on WPF1 ReportingFacilityInterface object)
I've created my WCF "service" class and contracts.
I'm using a proxy dll to facilitate the communication.
Here's the sequence of events:
1)WPFApp1 starts up and instantiates an instance of the exposed service class
ReportingFacilityInterface = new ReportingFacility.ReportingFacilityInterface();
This starts up fine.
2) WPFApp2 startsup and initializes instance of proxy object
reportingFacilityProxy = new ReportingFacilityInterfaceProxy.ReportingFacilityProxy();
This instantiates the proxy object, which results in this getting called:
reportingFacilityInterface = DuplexChannelFactory<IReportingFacilityInterface>.CreateChannel(objContext, "RPIEndPointConfiguration");
This seems to run and return successfuly.
3) WPFApp2 calls a on the object (through the proxy)
reportingFacilityInterface.Initialize(configuration);
I get an exception with the following detail:
Could not connect to net.tcp://localhost:8732/ReportingFacility.
The connection attempt lasted for a time span of 00:00:02.1931255.
TCP error code 10061: No connection could be made because the target machine actively refused it 127.0.0.1:8732
I examined my current port usage using the CurrPorts application and noticed that port #8732 does is not in the list of currently active/used ports on my machine.
Since I'm pretty green # the world of WCF, I'm kind of stumped here.
As I mentioned above, all these are running on the same (dedicated) piece of Windows 7 hardware, so permissions/roles should not be an issue.
I think I'm pretty close here, but am just missing something.
Thanks,
JohnB
I'd:
Verify your server config to be sure about service endpoint address
Run the Service Trace Viewer Tool (SvcTraceViewer.exe)
Add some basicHttpBinding endpoint to be sure you can access it from your browser
I resolved the same issue by going to services and start Net.tcp listener adapter.
Also, you can find more solutions here
http://blogs.ajithbhat.com/2010/06/tcp-error-code-10061-no-connection.html

No response from sever on external IP in client-server IM app

I'm following a tutorial # http://www.geekpedia.com/tutorial239_Csharp-Chat-Part-1---Building-the-Chat-Client.html to try and gather the basics of networking. For those not wanting to hit the jump, it's a quick tut demonstrating how to program a simple client-server-model chat application.
When I try and run the code in the tut, it works fine as long as both the client and the server are on the same network, but the second I try and do it externally (getting a mate to run the client app, and running the server app my side), it all goes to pot. The fact that the code works when in the same network leads me to believe that it's not a coding issue, but an issue with the way my network is set up.
I'm trying to run the server on my IP address at port 21719, which I have opened, but still other people can't connect to my server, not able to get any form of response at all.
The code (from the tut) that is being used for the server to listen to connections is:
public void StartListening()
{
IPAddress ipaLocal = ipAddress; //ipAddress is parsed from txtIP
tlsClient = new TcpListener(ipaLocal, 21719);
tlsClient.Start();
ServRunning = true; //for the running loop
// Start the new tread that hosts the listener
thrListener = new Thread(KeepListening);
thrListener.Start();
}
Now, the tutorial does actually point out that
IPAddress ipaLocal = ipAddress;
Will cause issues on some configurations, and I'm beginning to fear that my configuration may be included in that.
So, does anyone have any solution for me?
Thanks,
Sam
What is the local IP address that you're using? (ipAddress) If it's 127.0.0.1, that's not correct (I don't know how it would work internally either, but Windows seems to use magic from time to time). Also, if you have multiple NICs in your local machine, maybe the port forwarding is only set up to forward to one of them, and you're using the IP of the other?
If that's not the problem, here are a few generic suggestions:
Grab a copy of netcat. It's a small network testing util whose only job is to form a simple TCP connection. That will allow you to eliminate your code as a variable in all this. If netcat can form a connection, then you know the problem is your code. If not, you've confirmed that it's your router.
You can use WireShark (or TShark) to look for ICMP packets. Capture ICMP packets on the remote machine. If you get "Destination Unreachable" from the router, you've again proved that it's your router.
As Spencer said you need to make sure Port Forwarding is setup on your router, to forward all packets that come in on port 21719 to your internal machine. As for exactly how to do that, it's hard to say without knowing what type of router.
Are you having people use your external (internet) IP address? (See yours here.)
Have you pinholed your router to forward all communications from port 21719 to your server?
Some tips:
What kind of operating system are you using? Please check the Scope and/or Profiles (under Advanced tab) of your firewall rule.
While your friend is trying to telnet to the port (connect to the im server) monitor the traffic using Wireshark or Network Monitor (Wireshark have problems with Vista and Win 7). If you don't see anything hitting your machine the problem is probably on the router side. Double check the settings - you said you set the forward rule (NAT) but did it also set the rule on firewall of your router?

Categories