I have a 'honeypot' that I am developing in C# that listens on a series of ports (user inputted). It is a large project/windows service that functions as expected for almost any port entered and will not listen on ports that currently have something listening already. The problem is that when I test the service using telnet or netcat, opening a connection on port 23 is not caught by my service and therefore establishes the connection.
I open the ports in the firewall by doing the following:
for (int i = 0; i < ports.Length; i++)
{
string arg = "advfirewall firewall add rule name=\"PeepHole Open" + "\" dir=in action=allow protocol=TCP localport=" + ports[i];
string arg1 = "advfirewall firewall add rule name=\"PeepHole Open" + "\" dir=in action=allow protocol=UDP localport=" + ports[i];
ProcessStartInfo procStartInfo = new ProcessStartInfo("netsh", arg);
ProcessStartInfo procStartInfo1 = new ProcessStartInfo("netsh", arg1);
procStartInfo.RedirectStandardOutput = true;
procStartInfo1.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo1.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
procStartInfo1.CreateNoWindow = true;
Process.Start(procStartInfo1);
Process.Start(procStartInfo);
}
And I start the listeners by:
IPEndPoint Ep = new IPEndPoint(IPAddress.Parse("0.0.0.0"), current_port);
//TcpListener tempListener = new TcpListener(hostIP, current_port);
TcpListener tempListener = new TcpListener(Ep);
TCP_Listener listen = new TCP_Listener(); //my defined tcplistener struct
listen.listener = tempListener; //set the Listener's TcpListener field
listen.port = current_port; //set the Listener's Port field
listen.listener.Start(); //start this particular TcpListener
tcp_listener_list.Add(listen); //add the struct to the list of Listeners
And accept the TCP connection by:
for (int i = 0; i < tcp_listener_list.Count - 1; i++)
{
if (tcp_listener_list[i].listener.Pending())
{
TcpClient client = tcp_listener_list[i].listener.AcceptTcpClient();
int clientPort = tcp_listener_list[i].port;
IPEndPoint ep = client.Client.RemoteEndPoint as IPEndPoint;
ThreadPool.QueueUserWorkItem(LogTCP, new object[] { client, clientPort, ep });
}
}
And in LogTCP I close the connection by (where client is a TcpClient object):
NetworkStream networkStream = client.GetStream();
networkStream.Close();
client.Close(); //close the connection, all the data is gleaned from the attacker already
Now the problem is that when I run telnet or netcat to test the closing and logging of the port, my code is never executed and the connection is established because the port is opened; the TCP connection never is .Pending() and if I remove that, the issue is persistent. Also, I have the same issue if I set up the listeners to use IPAddress.Any and if I reconfigure my accept method to AcceptSocket with or without the .Pending() if statement. Does windows treat certain ports differently on a low level with certain programs?
I am running a windows service from Windows 8.1 and sending TCP connections through telnet on putty (on the machine that the service is installed on) and telnet and netcat on a Linux VM. Both Telnet Client and Telnet Server are disabled on the 'host' machine.
I have tried many different variations of closing the sockets and connections that I found during my researching.
client.Client.Close() produces an ObjectDisposedException
client.Client.Shutdown(SocketShutdown.Both) makes all previously 'working' ports hang connections with CLOSE_WAIT
I think the key here, is you mention as an aside that you have created your own struct. Structs are very tricky. You might think that the below code will end up with a TCP_Listener instance that has your tempListener and current_port. But if you set a breakpoint you'll probably notice otherwise. Every modification you do on a struct actually returns a brand new struct, so you can't assign fields one at a time like you do with a class.
TCP_Listener listen = new TCP_Listener(); //my defined tcplistener struct
listen.listener = tempListener; //set the Listener's TcpListener field
listen.port = current_port; //set the Listener's Port field
listen.listener.Start();
I would recommend, rather than a struct, you use a class. Or you initialize your struct as new TCP_Listener(tempListener, current_port), then Start it.
That is at least part of your problem. Once you fix that, let us know if it's still not working and we can look at the next issue.
Pending is never needed. Just continually accept on all listeners. Start one task per listener to do that:
while (true) {
ProcessConnectionAsync(await listener.AcceptAsync());
}
Something like this.
And here is an off-by-one bug: tcp_listener_list.Count - 1. But that bug goes away when you do it as explained above.
Regarding closing, why not just client.Dispose();? This is the normal way to do resource management in .NET. Nothing else is required.
Related
I have searched for 2 days and found many, many questions/answers to what appears to be this same issue, with some differences, however none really seem to provide a solution.
I am implementing a library for controlling a DMX system (ColorKinetics devices) directly without an OEM controller. This involves communicating with an Ethernet-enabled power supply (PDS) connected to my home LAN, through a router, which drives the lighting fixtures. The PDS operates on a specific port (6038) and responds to properly formatted datagrams broadcast over the network.
I can successfully broadcast a simple DMX message (Header + DMX data), which gets picked up by the PDS and applied to connected lighting fixtures, so one-way communication is not an issue.
My issue is that I am now trying to implement a device discovery function to detect the PDS(s) and attached lights on the LAN, and I am not able to receive datagrams which are (absolutely) being sent back from the PDS. I can successfully transmit a datagram which instructs the devices to reply, and I can see the reply coming back in WireShark, but my application does not detect the reply.
I also tried running a simple listener app on another machine, which could detect the initial broadcast, but could not hear the return datagram either, however I figure this wouldn't work since the return packet is addressed to the original sender IP address.
I initially tried implementing via UdpClient, then via Sockets, and both produce the same result no matter what options and parameters I seem to specify.
Here is my current, very simple code to test functionality, currently using Sockets.
byte[] datagram = new CkPacket_DiscoverPDSRequestHeader().ToPacket();
Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("192.168.1.149"), 6039);
public Start()
{
// Start listener
new Thread(() =>
{
Receive();
}).Start();
sender.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
sender.EnableBroadcast = true;
// Bind the sender to known local IP and port 6039
sender.Bind(ep);
}
public void Send()
{
// Broadcast the datagram to port 6038
sender.SendTo(datagram, new IPEndPoint(IPAddress.Broadcast, 6038));
}
public void Receive()
{
Socket receiver = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
receiver.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
receiver.EnableBroadcast = true;
// Bind the receiver to known local IP and port 6039 (same as sender)
IPEndPoint EndPt = new IPEndPoint(IPAddress.Parse("192.168.1.149"),6039);
receiver.Bind(EndPt);
// Listen
while (true)
{
byte[] receivedData = new byte[256];
// Get the data
int rec = receiver.Receive(receivedData);
// Write to console the number of bytes received
Console.WriteLine($"Received {rec} bytes");
}
}
The sender and receiver are bound to an IPEndPoint with the local IP and port 6039. I did this because I could see that each time I initialized a new UdpClient, the system would dynamically assign an outgoing port, which the PDS would send data back to. Doing it this way, I can say that the listener is definitely listening on the port which should receive the PDS response (6039). I believe that since I have the option ReuseAddress set to true, this shouldn't be a problem (no exceptions thrown).
Start() creates a new thread to contain the listener, and initializes options on the sending client.
Send() successfully broadcasts the 16-byte datagram which is received by the PDS on port 6038, and generates a reply to port 6039 (Seen in WireShark)
Receive() does not receive the datagram. If I bind the listener to port 6038, it will receive the original 16-byte datagram broadcast.
Here is the WireShark data:
Wireshark
I have looked at using a library like SharpPCap, as many answers have suggested, but there appear to be some compatibility issues in the latest release that I am not smart enough to circumvent, which prevent the basic examples from functioning properly on my system. It also seems like this sort of basic functionality shouldn't require that type of external dependency. I've also seen many other questions/answers where the issue was similar, but it was solved by setting this-or-that parameter for the Socket or UdpClient, of which I have tried every combination to no avail.
I have also enabled access permissions through windows firewall, allowed port usage, and even completely disabled the firewall, to no success. I don't believe the issue would be with my router, since messages are getting to Wireshark.
UPDATE 1
Per suggestions, I believe I put the listener Socket in promiscuous mode as follows:
Socket receiver = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
receiver.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, true);
receiver.EnableBroadcast = true;
IPEndPoint EndPt = new IPEndPoint(IPAddress.Parse("192.168.1.149"), 0);
receiver.Bind(EndPt);
receiver.IOControl(IOControlCode.ReceiveAll, new byte[] { 1, 0, 0, 0 }, null);
This resulted in the listener receiving all sorts of network traffic, including the outbound requests, but still no incoming reply.
UPDATE 2
As Viet suggested, there is some sort of addressing problem in the request datagram, which is formatted as such:
public class CkPacket_DiscoverPDSRequest : BytePacket
{
public uint magic = 0x0401dc4a;
public ushort version = 0x0100;
public ushort type = 0x0100;
public uint sequence = 0x00000000;
public uint command = 0xffffffff;
}
If I change the command field to my broadcast address 192.168.1.149' or192.168.255.255`, my listener begins detecting the return packets. I admittedly do not know what this field is supposed to represent, and my original guess was to just put in a broadcast address since the point of the datagram is to discover all devices on the network. This is obviously not the case, though I am still not sure the exact point of it.
Either way, thank you for the help, this is progress.
So in actuality it turns out that my issue was with the formatting of the outgoing datagram. The command field needs to be an address on the local subnet 192.168.xxx.xxx, and not 255.255.255.255... for whatever reason this was causing the packet to be filtered somewhere before getting to my application, though WireShark could still see it. This may be common sense in this type of work but being relatively ignorant as to network programming as well as the specifics of this interface it wasn't something I had considered.
Making the change allows a simple UdpClient send/receive to function perfectly.
Much thanks to Viet Hoang for helping me find this!
As you've already noted, you don't need to bind to send out a broadcast but it uses a random source port.
If you adjust your code to not bind the sender, your listener should behave as expected again:
Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sender.EnableBroadcast = true;
Thread read_thread;
public Start()
{
// Start listener
read_thread = new Thread(Receive);
read_thread.Start();
}
The issue you've bumped into is that the operating system kernel is only delivering packets up to one socket binder (first come first serve basis).
If you want true parallel read access, you'll need to look into sniffing example such as: https://stackoverflow.com/a/12437794/8408335.
Since you are only looking to source the broadcast from the same ip/port, you simply need to let the receiver bind first.
If you add in a short sleep after kicking off the receive thread, and before binding the sender, you will be able to see the expected results.
public Start()
{
// Start listener
new Thread(() =>
{
Receive();
}).Start();
Thread.Sleep(100);
sender.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
sender.EnableBroadcast = true;
// Bind the sender to known local IP and port 6039
sender.Bind(ep);
}
Extra note: You can quickly test your udp sockets from a linux box using netcat:
# echo "hello" | nc -q -1 -u 192.168.1.149 6039 -
- Edit -
Problem Part #2
The source address of "255.255.255.255" is invalid.
Did a quick test with two identical packets altering the source ip:
https://i.stack.imgur.com/BvWIa.jpg
Only the one with the valid source IP was printed to the console.
Received 26 bytes
Received 26 bytes
I have a need to talk to multiple devices on a private LAN using a proprietary UDP protocol. In a production setting we have a industrial PC running a C++ application that can connect to multiple devices and communicate freely with them. I am trying to duplicate that communication using C# for a windows application that technicians, testers and others would be using. I have probably done this myself a thousands times in c++ but c# seems to be giving me all sorts of fits.
I have one UDP listener listening on Any IP and specific Port. This port is different from the device command port. This receives a periodic heartbeat from each device. From this communication I am able to get the specific IP and command Port for that device. The program maintains a list of devices and displays that lists to the user. The user can then select a specific device and inspect it more for more details.
If there are several devices with the same port number the program will not be able to inspect those devices at the same time. When the user selects the device the program creates a new instance of the UdpClient. In pseudo-code form:
udpConnection = new UdpClient();
udpConnection.ExclusiveAddressUse = false;
udpConnection.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpConnection.Client.Bind(localEndpoint);
udpConnection.Client.Connect(remoteEndpoint);
Local Endpoint is the Local interface IP and the Device Port Number of the machine the application is running on. Remote EndPoint is the Device IP and Device Port that the application wants to inspect further.
As anyone had similar issues and what have you done to get around it?
Thanks in advance
Update sample network diagram and further explanation:
Network Diagram
In the image I will be able to have two windows viewing Device A and C or B and C simultaneously with no issues. However if I have Device A and C the window that I opened second will not get any communications updates until I close the first window. If I "sniff" the network with WireShark I see all the communications as I would expect.
Code Snippet:
private void ClientThread()
{
IPEndPoint myEndPoint;
myLogger = LogManager.GetLogger("ClientLogs");
myLogger.Debug("Client Started!");
IPAddress ClientAddress = System.Net.IPAddress.Parse(ClientIP);
myIP = "10.0.0.4"; // Currently hard-coded local interface IP
IPAddress thisAddress = System.Net.IPAddress.Parse(myIP);
ClientEndPoint = new IPEndPoint(ClientAddress, Convert.ToInt32(ClientPort));
myEndPoint = new IPEndPoint(thisAddress, Convert.ToInt32(ClientPort)); // Both forms launch but only the first one will receive data.
//myEndPoint = new IPEndPoint(thisAddress, 0); // Both forms will launch but no data received (packets do show being received in wireshark)
//myEndPoint = new IPEndPoint(IPAddress.Any, ClientPort); // Both forms launch but only the first one will receive data.
try
{
myUDP = new UdpClient();
myUDP.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); // "Only one usage of each socket address (protocol/network address/port) is normally permitted" Exception when removed.
myUDP.ExclusiveAddressUse = false; // No difference if this is removed
myUDP.Client.Bind(myEndPoint); // Neither form will receive data if this is removed
myUDP.Client.Connect(ClientEndPoint); // removing this will allow the forms to launch but again the only the first will receive data
}
catch (Exception ex)
{
myUDP = null;
myLogger.Fatal(String.Format("Error in setting up UDP Client: {0}", ex.Message));
return;
}
myLogger.Debug(String.Format("Attempt to connect to : {0} on {1}", ClientIP, Convert.ToInt32(ClientPort)));
byte[] bytes = new byte[1452];
try
{
while (ThreadLoop)
{
IPEndPoint newEndPoint = new IPEndPoint(IPAddress.Any, 0);
Byte[] receiveBytes = myUDP.Receive(ref newEndPoint);
ParseProtocolPacket(ref receiveBytes); // Code to parse the data received
}
}
catch (Exception Ex)
{
myLogger.Debug("Client Socket Other Error: " + Ex.Message);
}
}
I think your problem is here:
udpConnection.Client.Bind(localEndpoint);
This line, if I understand correctly, is telling it to use the same local port to make the outbound request. But you already have another UdpClient listening on that port, so Windows won't know which one to send the traffic to (or it just sends it to the first one).
You should be able to just not use Bind() here. Without it, when you call Connect(), it will assign a random local port, which is the way most outbound network requests work.
Or if you need to specify the network interface, then pass 0 for the port and Windows will assign one:
localEndpoint = new IPEndPoint(ipAddress, 0);
I'm trying to send many small (~350 byte) UDP messages to different remote hosts, one packet for each remote host. I'm using a background thread to listen for responses
private void ReceivePackets()
{
while (true)
{
try
{
receiveFrom = new IPEndPoint(IPAddress.Any, localPort);
byte[] data = udpClientReceive.Receive(ref receiveFrom);
// Decode message & short calculation
}
catch (Exception ex)
{
Log("Error receiving data: " + ex.ToString());
}
}
}
and a main thread for sending messages using
udpClientSend.SendAsync(send_buffer, send_buffer.Length, destinationIPEP);
Both UdpClient udpClientReceive and UdpClient udpClientSend are bound to the same port.
The problem is SendAsync() takes around 15ms to complete and I need to send a few thousand packets per second. What I already tried is using udpClientSend.Send(send_buffer, send_buffer.Length, destination);which is just as slow. I also set both receive/send buffers higher and I tried setting udpClientSend.Client.SendTimeout = 1; which has no effect. I suspect it might have to do with the remote host changing for every single packet? If that is the case, will using many UDPclients in seperate threads make things faster?
Thanks for any help!
Notes:
Network bandwidth is not the problem and I need to use UDP not TCP.
I've seen similar questions on this website but none have a satisfying answer.
Edit
There is only one thread for sending, it runs a simple loop in which udpClientSend.SendAsync() is called.
I'm querying nodes in the DHT (bittorrent hashtable) so multicasting is not an option (?) - every host only gets 1 packet.
Exchanging UDPClient class with the Socket class and using AsyncSendTo() does not speed things up (or insignificantly).
I have narrowed down the problem: Changing the remote host address to some fixed IP & port increases throughput to over 3000 packets/s. Thus changing the destination address too often seems to be the bottleneck.
I'm thinking my problem might be related to UDP "Connect"-Speed in C# and UDPClient.Connect() is slowing down the code. If so, is there a fix for this? Is it a language or an OS problem?
Why are you using UdpClient Connect before sending? It's an optional step if you want to set a default host. Looks like you want to send to multiple destinations so you can set the remote host each time you call the Send method.
If you decide to remove the Connect method you may see an improvement, but it still looks like you have a bottleneck somewhere else in your code. Isolate the Send calls and measure time then start adding more steps until you find what's slowing you down.
var port = 4242;
var ipEndPoint1 = new IPEndPoint(IPAddress.Parse("192.168.56.101"), port);
var ipEndPoint2 = new IPEndPoint(IPAddress.Parse("192.168.56.102"), port);
var buff = new byte[350];
var client = new UdpClient();
int count = 0;
var stopWatch = new Stopwatch();
stopWatch.Start();
while (count < 3000)
{
IPEndPoint endpoint = ipEndPoint1;
if ((count % 2) == 0)
endpoint = ipEndPoint2;
client.Send(buff, buff.Length, endpoint);
count++;
}
stopWatch.Stop();
Console.WriteLine("RunTime " + stopWatch.Elapsed.TotalMilliseconds.ToString());
Hi I am using TCPCLient and TCPlitner to transmit data but i am getting error not to connect
below is my Code
private void button1_Click(object sender, EventArgs e)
{
TcpClient tcpc = new TcpClient("192.168.21.46", 10);
NetworkStream nts = tcpc.GetStream();
if (nts.CanWrite)
{
Byte[] sends = System.Text.Encoding.ASCII.GetBytes(textBox1.Text.ToCharArray());
nts.Write(sends, 0, sends.Length);
nts.Flush();
}
}
private void button2_Click(object sender, EventArgs e)
{
TcpListener myListener = new TcpListener(10);
myListener.Start();
while (true)
{
//Accept a new connection
Socket mySocket = myListener.AcceptSocket();
if (mySocket.Connected)
{
//make a byte array and receive data from the client
Byte[] receive = new Byte[64];
int i = mySocket.Receive(receive, receive.Length, 0);
char[] unwanted = { ' ', ' ', ' ' };
string rece = System.Text.Encoding.ASCII.GetString(receive);
label1.Text = rece.TrimEnd(unwanted);
}
}
}
this two buttons i have added in the same form and Ip apddress which is mentioned is my systems IP Address. Can anyone tell me why this Happen. Even I remove firewall setting also.
First of all your UI will hang on button 2 click because it's stuck on the while(true) loop so use BeginAcceptSocket(IAsyncResult r, Object state) for async.
Second you must use the loopback address or otherwise the firewall should block the port 10 assuming that it's not open. Also the TcpListener(int port) is obsolote and its better to use the TcpListener(IPAddress localddr, int port) and use both the loopback address.
I'm assuming you have two different programs and one is listening while the other is sending. If you don't, separate them out. I'm thinking you have a networking issue but can't say precisely why it's blocked.
You're using port 10, which generally is too low for arbitrary application uses even if it's not currently occupied. If you're building a custom protocol, try to listen on a port above approximately 1000 (more a rule of thumb). You can look here http://technet.microsoft.com/en-us/library/cc959828.aspx or google for "tcp well known ports" for more details and to ensure you don't have a collision.
Try running your TCP listener, then open a command prompt and typing the following
telnet localhost 10
or use the port number you change 10 to. I tried your code and was able to connect to port 10 without issue. If you don't have the "telnet" program you can turn the feature on in your Windows. (search "feature" and choose "turn windows feature on or off" then turn "Telnet Client" on)
If the telnet program connects, you'll know that the issue isn't connectivity related. If the telnet program fails to connect then you'll know something is still blocking that port. Try a different port and re-test connectivity. Once telnet connects, you can then focus on the TCP client portion of your program.
NetFoss requires you to run it with a command line similar to this:
nf.bat /n[#] /h[#] [command line]
where /n[#] is a node number and /h[#] is an OS socket handle.
I want to write something in C# very similar to what a telnet BBS would do when it runs door games. It should accept the client socket, gather a bit of information passed into it from the client, then pass the socket over to NetFoss to be used to run a DOS based application that supports communications via a fossil driver.
I honestly was just guessing about how to go about this, and here's what I came up with:
class Program
{
const int BACKLOG_SIZE = 20;
static void Main(string[] args)
{
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Bind(new IPEndPoint(IPAddress.Any, 3102));
server.Listen(BACKLOG_SIZE);
while (true)
{
Socket socket = server.Accept();
Process p = new Process();
p.EnableRaisingEvents = false;
p.StartInfo.FileName = #"c:\netfoss\nf.bat";
p.StartInfo.Arguments = #"/n1 /h" + socket.Handle + #" c:\game\game.bat 1";
p.StartInfo.WorkingDirectory = "c:\netfoss";
p.StartInfo.UseShellExecute = false;
p.Start();
}
}
}
Interestingly enough, the application that NetFoss is running via game.bat is being output to the C# application's console window but not the telnet client, and even more interesting is that the telnet client DOES receive the initial NetFoss message that shows it is able to communicate with the socket. So, why is the application that is passed to NetFoss outputting to my console window instead of the telnet client?
Anyone know what I'm missing?
EDIT:
I forgot to mention that I also tried setting UseShellExecute to TRUE, and this throws a NetFoss error saying that it is an invalid handle. From my understanding, I would have to duplicate the handle in some way so that the unmanaged application can access it? Is there any way to accomplish what I'm trying to do using C#?
Thanks,
Marc
It is normal that the DOS application outputs to your console window, but it should also output to the telnet client.
Since you are seeing the initial NetFoss version message in your telnet client, we know that the socket handle is being sucesfully passed to NetFoss... So it sounds like the problem is that your DOS application is not FOSSIL aware, or is not currently configured to use a FOSSIL or an INT14h communications method.
Regards, Mike
NetFoss developer