tcp connection to router how to communicate? (Telnet Client) - c#

I am trying to build a program that will connect to an IP address (preferably that of a router) to a specific port (mainly 80) and will try to authenticate and then go on with further actions.
I started without knowing how to communicate with the router/server so i did this:
while (tcpSocket.Available > 0)
{
int input = tcpSocket.GetStream().ReadByte();
But it always gets a tcpSocket.Available = 0
So then i found out that i have to send a specific cmd for it to talk to me.
http://msdn.microsoft.com/en-us/library/cc247846.aspx
and made this
var client = new TcpClient(ip, port);
var data = Encoding.GetEncoding(1252).GetBytes(cmd);
var stm = client.GetStream();
stm.Write(data, 0, data.Length);
Now I dont understand how to format the cmds the cmd based on this http://www.ietf.org/rfc/rfc2941.txt
Would be 37 - 1?
Thank you for reading
P.S dont know if i should point this to SuperUser or ServerFault

I think you need to go back to simpler questions and investigations.
First: What protocol is actually running on the server you are connecting to? Port 80 suggests it is HTTP (port 80 is typically reserved for HTTP). Telnet typically runs on port 23.
If it is HTTP you need to follow the protocol defined in RFC 2616 (with the authentication options defined in RFC 2617).
Even simpler yet: connect to the server using PuTTY (or other preferred telnet client). What do you need to do in order to log in? If it is a telnet server then it will probably show a banner followed by a login prompt. You will type the username followed by return, then it will show you a password prompt. If it is a HTTP server then it will probably show you nothing at all, but type HTTP/1.0 (return) HEAD / (return) and you should see a HTTP message response. Whatever you need to do using PuTTY, your program will need to do exactly the same thing.

Related

c# proxy ssl / tls passthrough without certificate

This is the issue.
I have an https request. The request is is being sent as an SSL / TLS request (Not the CONNECT .... that comes from a browser with the proxy setup).
I need to write a proxy in c# that blocks a specific https://foo.com/foo.htm request but lets through https://foo.com/anything_else.htm.
I can do this fine creating a MITM attack with a new certificate etc etc.
But Im now wondering if there is an easy way to do this Im missing without using a MITM attack as I have no need to decrypt the data. I only need to know the URI/file.
I can easily just transfer streams but I want to know if there is a simple way to transfer the streams after I have read the URI and file.
I can write some fancy code to pull apart the tcp request and thats what I may have to do.
Anybody any ideas before I go down this path. Remember there is no CONNECT request. Just direct SSL / TLS.
The main reason for this is it just makes things simpler not creating self signed certificates etc.
Maybe its even possible to use the real certificate somehow from the server end as I dont need to decrypt any of the no header data.
I find the networking side of c# is not very well documented and a little all over the place.
Just for reference i can get the URI from the TcpClient using:
IPEndPoint ipEndPoint = (IPEndPoint)clientTcpClient.Client.RemoteEndPoint;
IPAddress ipAddress = ipEndPoint.Address;
// Get the hostname.
IPHostEntry ipHostEntry = Dns.GetHostEntry(ipAddress);
String hostName = ipHostEntry.HostName;
// Get the port.
Int32 port = ipEndPoint.Port;
But not the requested page.
While the target hostname might be visible in the TLS handshake as SNI extension or by analyzing the certificate returned by the server the path component of the URL is only contained in the HTTP request. Since this HTTP request is only done after TLS handshake and the request is thus already encrypted you cannot get to the full path without decrypting the request. This means that blocking access to a specific path is not possible without SSL man in the middle and thus requires a certificate for the target site owned by the man in the middle and trusted by the client.
Not that this is true for CONNECT requests too since these requests only contain the target hostname but the path component is again only contained in the encrypted HTTP request sent inside the tunnel created by CONNECT.

Using WinSocks in C to send data to a c# application on same machine, "target host refusing connectiong(c# part)

I am trying to get data from my interface, written in c, to another application, in c#.
Now, I'm not sure if WinSocks is pure c, but I'm using visual studio and the rest of my interface is 100% pure C.
Here is my "client" written in c#
http://pastebin.com/X9SNcVqn
here is my "server" written in c - loops waiting for a connection, this builds AND RUNS without issues
NOTE: DEFAULT_PORT is 18042, used the same port for client and server side.
I've downloaded wireshark and used the command "tcp.port eq "
http://pastebin.com/FHZyre2V
I also tried going through my windows firewall and NORTON to allow this connection, I couldn't figure out what to do. Most of the tuts I saw where outdated and tabs and options are changed in WINDOWS 7
I chose a port that wasn't being used, I tried using wireshark to see the connections, no luck BUT I scanned the port I used with nmap, before AND after I ran the "server", so it must of atleast have been created
In your C# code you are mixing TcpClient and Socket objects. You don't need both, only the TcpClient. (The Socket code is using the wrong port as well). Once the TcpClient object is connected, call the GetStream method to get a NetworkStream object that you can read and write to to send and receive data to the server process.
See the example code in the documentation, here: http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.aspx
Your client code contains:
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("192.168.1.4"), 18041);
I would not necessarily expect the IP address bound to a network card to necessarily work for localhost-to-localhost connections. I'd recommend changing your client to use 127.0.0.1 or another suitable loopback address.
First,check if the IP adress is correct and if the corresponding port is listeing.
netstat -an | find "port number"
and I think, in the server side code
local.sin_port = (unsigned short)DEFAULT_PORT;
Should be:
local.sin_port = htons((unsigned short)DEFAULT_PORT);

.NET SslStream is not working

I am trying inialise a tls tunnel with the .net SslStream but after opening the stream I always get the following error:
"Unable to read data from the transport connection: An established connection was aborted by the software in your host machine."
After I establish a tls connection and after sending a second message.
I've been searching for an answer for the last four days but there isn't any helpful information online!
edit:
I am trying to connect to talk.google.com
and I'm using the code sample from MSDN. Only difference is that I'm sending data before and when it is time to use tls i do the following:
public void SecureStream()
{
netStream.Flush();
sslStream = new SslStream(netStream, false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
sslStream.AuthenticateAsClient("talk.google.com");}
edit: I managed to eliminate the first error (small bug on how i was handling the send) now I always get
"Unable to read data from the transport connection: An established connection was aborted by the software in your host machine."
edit2: Im not sending any whitespaces I rewrote the message passing part and I still have the same problem.
I start with
String streamInit = "<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='google.com' version='1.0'>";
client.Send(streamInit);
Then on receive I have the following
static void client_MessageReceived(SyncronousClient source, string Result)
{
if (Regex.IsMatch(Result, "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"><required/></starttls>"))
{
String startTlS = "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>";
source.Send(startTlS);
}
else if (Regex.IsMatch(Result, "<proceed xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>"))
{
//Do TLS Magic
source.SecureStream();
String streamReInit = "<stream:stream xmlns='jabber:client'xmlns:stream='http://etherx.jabber.org/streams'to='google.com'version='1.0'>";
source.Send(streamReInit);
}
else if (Regex.IsMatch(Result, "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"))
{
//String AuthType = "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='X-GOOGLE-TOKEN'/>";
String AuthType = "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"PLAIN\"/>";
source.Send(AuthType);
}}
It's unlikely to be your problem (unless .Net has started doing SNI under the covers), but when you call AuthenticateAsClient, pass in the same domain name that you used in your stream's to attribute (in this case, google.com). As well, you might need gmail.com instead of google.com:
sslStream.AuthenticateAsClient("gmail.com", null, SslProtocols.Tls, false);
As csharptest.net alluded to, make sure you don't have a keepalive timer that sends extra whitespace, or wait to start the timer until after TLS works. The only other way I can imagine your getting that error is if you don't have a ciphersuite that the server implements, but I know the .Net SslStream works against GTalk.
Lastly, use one of the existing .Net libraries for XMPP (there are 5 listed here), and you can start writing much more fun code right away. You're about to run into the inadequacies of the .Net XML system, and your regex-based approach won't work when you start getting partial stanzas or multiple stanzas in a single read.
That really doesn't make sense to me. The server, if using SSL, requires that the client perform the SSL handshake upon connection. Thus, I'm not sure what you mean by "I'm sending data before...". It sounds like your not immediately calling the AuthenticateAsClient. If this is the case, I suspect that is your problem. AFAIK, you cannot use the same socket/connection connection for both SSL and non-SSL communications. Either the server requires SSL, or it does not support it, it should never do both.
My previous answer above was in ignorance. Indeed it appears that the standard does in fact require that the connect send and receive data prior to the initialization of the SSL handshake. Really odd that they would do that... but whatever. After briefly reading through parts of the RFC it appears that you are expected to begin the SSL client auth immediately after the closing '>'. No trailing whitespace allowed which may be your problem?

XMPP TLS connection with SslStream

I am trying to create a simple xmpp client that connects to Gtalk.
The first part of the handshake seems to work.
Ror the TLS handshake I created a client SslStream, connected to the intended server (talk.google.com) and successfully got authenticated .
The first SSlStream.Read is to receive the greeting reply, it went fine . I do a SslStream.write to send my first command, but when i do my Sslstream.Read() to get the reply , i get this error."System.IO.IOException: Unable to read data from the transport connection: An established connection was aborted by the software in your host machine."
Can anyone point me to the right direction?
I am using code very similar to the example on msdn http://msdn.microsoft.com/en-us/library/system.net.security.sslstream.aspx
except that I switch from a Network stream to a Sslstream when TLS is negotiated.
netStream.Flush();
sslStream = new SslStream(netStream,
true,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
sslStream.AuthenticateAsClient("talk.google.com");
I'd try using one of the existing XMPP libraries for .Net:
Jabber-Net: http://code.google.com/p/jabber-net/
agsXMPP: http://www.ag-software.de/agsxmpp-sdk/
Even if you don't use of these libs, you'll get some good ideas from looking at the code.
In this case, you probably want:
sslStream.AuthenticateAsClient("gmail.com");
where gmail.com is the domain name from the JID you're trying to log in as.

The server returned an address in response to the PASV command that is different than the address to which the FTP connection was made

System.Net.WebException: The server returned an address in response to the PASV command that is different than the address to which the FTP connection was made.
at System.Net.FtpWebRequest.CheckError()
at System.Net.FtpWebRequest.SyncRequestCallback(Object obj)
at System.Net.CommandStream.Abort(Exception e)
at System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage)
at System.Net.FtpWebRequest.GetRequestStream()
at BackupDB.Program.FTPUploadFile(String serverPath, String serverFile, FileInfo LocalFile, NetworkCredential Cred) in D:\PROJEKTI\BackupDB\BackupDB\Program.cs:line 119
code:
FTPMakeDir(new Uri(serverPath + "/"), Cred);
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverPath+serverFile);
request.UsePassive = true;
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = Cred;
byte[] buffer = new byte[10240]; // Read/write 10kb
using (FileStream sourceStream = new FileStream(
LocalFile.ToString(), FileMode.Open))
{
using (Stream requestStream = request.GetRequestStream())
{
int bytesRead;
do
{
bytesRead = sourceStream.Read(buffer, 0, buffer.Length);
requestStream.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
}
response = (FtpWebResponse)request.GetResponse();
response.Close();
}
omg. What's up with all the pandering here for buying their 3rd party solutions instead of informing you to change one line of code?
Try toggling the Passive value to see which works:
request.UsePassive = false;
This may depend on the firewall between the Machines (client and server).
I've noticed if I go through our firewall, then I need it left at True, otherwise it will return the Exception:
The remote server returned an error: (500) Syntax error, command
unrecognized.
However, if I'm behind the firewall (like two machines connecting directly to each other within a data-center) then I need to set it to False, otherwise it will return the Exception:
The server returned an address in response to the PASV command that is different than the address to which the FTP connection was
made.
If this works and you want to make your solution more adaptable, you could wrap your request in a try-catch block using the default True value, and if you get the 500 error, then switch UsePassive to False and try it again.
if anyone have the same problem, this is solution for proftpd
http://www.proftpd.org/docs/howto/NAT.html
In passive mode FTP conversation goes as follows:
client: PASV
(i would like to transfer files. Tell me which port and ip address should I use)
server: 227 Entering Passive Mode (172,16,3,4,204,173)
(ok, use port 52397 on IP address 172.16.3.4.)
client: connects to this IP address/port and starts data transfer.
It looks like the FTP server with two public IP address (e.g. 1.2.3.4) returns a private IP address as a response to PASV command.
Solution
Switching to Active mode.
In active mode FTP server connects to FTP client for data transfers. It would solve this issue, but is not firewall friendly. It will not work when incoming connections are blocked (very common).
Ignoring IP address send as response to PASV command
If the public ftp server IP address is a public one, and IP address returned as a response for PASV command is from private range (such as 10., 192.168.). In such case the FTP client should use the public IP address.
This is exactly what does our Rebex FTP do in such situation. It works well (this behavior can be switched off). It can be even turned on for servers with multiple public IP addresses.
I don't know whether similar workaround is possible with FtpWebRequest.
You can download trial and check whether it solves your problem.
After a lot of digging around I found the only way to solve this problem was to change the PASV settings on the server.
Fortunately I control both the client and server machines so I was able to tell the server (FileZilla in my case) to use the public IP rather than the private IP.
Your FTP server is misconfigured.
In the passive mode the server reports an IP address and port to which the client should connect to for a data transfer. Your FTP server reports its IP address within an internal network, although it's behind a firewall/NAT. The client cannot connect to that internal address for obvious reason. You have to configure the FTP server to report its external IP address.
How that's done is server-specific and you didn't tell us, what your FTP server is.
IIS: In IIS Manager, open FTP > FTP Firewall Support. See section Servers behind external Firewall/NAT in my guide to installing IIS server.
FileZilla FTP server: Go to Edit > Settings > Passive mode settings > IPv4 specific > External Server IP Address for passive mode transfers. See FTP server running on Port 2000 over NAT not working on Passive Mode.
ProFTPD: Use MasqueradeAddress directive.
vsftpd: pasv_address directive.
Some answer here suggest using the active mode.
request.UsePassive = false;
But that can help only if there's no firewall/NAT between the client and the server, in which case you won't have the problem in the first place (unless the server is really broken and reports a completely wrong IP address, not only the internal one). Or if the client's firewall/NAT is configured to allow inbound connections, what is not usual.
Another approach is using a different FTP library that can workaround the problem by ignoring the incorrect IP address reported by the server and using the primary/control connection IP address. Or by using the EPSV command instead of PASV command that implicitly uses the primary/control connection IP address.

Categories

Resources