【问题标题】:Trouble catching TCP traffic on port 23 - C#无法在端口 23 上捕获 TCP 流量 - C#
【发布时间】:2016-07-16 01:42:09
【问题描述】:

我有一个我正在用 C# 开发的“蜜罐”,它监听一系列端口(用户输入)。这是一个大型项目/Windows 服务,几乎可以对输入的任何端口按预期运行,并且不会监听当前已经监听的端口。问题是,当我使用 telnet 或 netcat 测试服务时,在端口 23 上打开连接没有被我的服务捕获,因此建立了连接。

我通过执行以下操作在防火墙中打开端口:

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);

        }

我通过以下方式开始听众:

 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

并通过以下方式接受 TCP 连接:

 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 });
      }
  }

在 LogTCP 中,我关闭连接(其中客户端是 TcpClient 对象):

 NetworkStream networkStream = client.GetStream(); 
 networkStream.Close();
 client.Close(); //close the connection, all the data is gleaned from the attacker already

现在的问题是,当我运行 telnet 或 netcat 测试端口的关闭和日志记录时,我的代码永远不会执行,因为端口已打开,所以连接已建立; TCP 连接永远不会是 .Pending() ,如果我删除它,问题就会持续存在。此外,如果我将侦听器设置为使用 IPAddress.Any 并且如果我将我的接受方法重新配置为带有或不带有 .Pending() if 语句的 AcceptSocket,我也会遇到同样的问题。 Windows 是否在某些程序的低级别上以不同的方式处理某些端口?

我正在从 Windows 8.1 运行 Windows 服务,并通过 putty 上的 telnet(在安装该服务的机器上)以及 Linux VM 上的 telnet 和 netcat 发送 TCP 连接。 “主机”机器上的 Telnet 客户端和 Telnet 服务器都被禁用。

我尝试了许多不同的方法来关闭我在研究期间发现的套接字和连接。

client.Client.Close() 产生 ObjectDisposedException client.Client.Shutdown(SocketShutdown.Both) 使所有以前“工作”的端口挂起与 CLOSE_WAIT 的连接

【问题讨论】:

    标签: c# windows sockets tcp telnet


    【解决方案1】:

    我认为这里的关键是,您在旁白中提到您创建了您自己的结构。结构非常棘手。您可能认为下面的代码最终会生成一个 TCP_Listener 实例,该实例包含您的 tempListener 和 current_port。但是,如果您设置断点,您可能会注意到其他情况。您对结构所做的每次修改实际上都会返回一个全新的结构,因此您不能像对类所做的那样一次分配一个字段。

    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();  
    

    我建议您使用类,而不是结构。或者你将你的结构初始化为 new TCP_Listener(tempListener, current_port),然后启动它。

    这至少是您问题的一部分。一旦你解决了这个问题,请告诉我们它是否仍然无法正常工作,我们可以查看下一个问题。

    【讨论】:

    • 实际上,当我看到它时,我很惊讶您没有收到 NullReferenceException。但是您分配结构的方式似乎不正确。它真的是一个结构吗?
    • 这对我有用。我想我对其他端口很幸运,端口 23 发现了这个意想不到的结果。我最终创建了一个简单的类来替换结构。谢谢!
    【解决方案2】:

    Pending 永远不需要。只是不断地接受所有听众。为每个侦听器启动一项任务:

    while (true) {
     ProcessConnectionAsync(await listener.AcceptAsync());
    }
    

    类似的东西。

    这里有一个单独的错误:tcp_listener_list.Count - 1。但是,当您按照上述说明进行操作时,该错误就会消失。

    关于关闭,为什么不只是client.Dispose();?这是在 .NET 中进行资源管理的常规方法。不需要其他任何东西。

    【讨论】:

    • 好收获。我将其更改为几乎在其他任何地方都有的 foreach 循环,并删除了 Pending() 调用。我想我只是在这个项目上获得了隧道视野。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2017-03-10
    • 2021-08-09
    • 2013-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多