为什么此端口扫描器代码有时会错过开放端口?
我正在尝试编写一个简单的连接端口扫描器。我正在 scanme.nmap.org 上针对前 10K 端口对其进行测试。它应该看到端口 22、80 和 9929。如果我扫描 1 - 10000,它会找到 22 和 80,但看不到 9929。如果我先扫描 9900 到 10000,然后扫描 1-10000(如下例所示),它会看到 9929 ,但经常看不到端口 80 或 22。
我知道我可以尝试通过以下方式使用 WinPcap .NET 包装器并进入较低级别,但是有没有办法让简单的 TCP 连接端口扫描器在没有 WinPcap 的情况下可靠地工作?
注意:我目前以 100 次为一组进行扫描,因为如果以更大的块进行扫描,结果会更差。
using System;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace ps
{
internal class Program
{
private const int batchSize = 100;
public static void Main(string[] args)
{
int minPort = Convert.ToInt32(args[0]);
int maxPort = Convert.ToInt32(args[1]);
int loops;
if (maxPort < batchSize)
{
loops = 1;
}
else
{
loops = maxPort/batchSize;
}
// If I look for 9929 in the inital 100 - I can find it
Parallel.For(9900, 10000, port =>
{
string host = "scanme.nmap.org";
bool res = TryConnect(host, port, 5000);
if (res)
{
Console.WriteLine("\nConnected: " + port + "\n");
}
});
// now loop through all ports in batches
// should see 22, 80 & 9929 but normally doesn't
for (int i = 0; i < loops; i++)
{
minPort = 1 + (i*batchSize);
if (loops != 1)
{
maxPort = batchSize + (i*batchSize);
}
Console.WriteLine("minPort:" + minPort + " maxPort:" + maxPort);
Parallel.For(minPort, maxPort, port =>
{
string host = "scanme.nmap.org";
bool res = TryConnect(host, port, 5000);
if (res)
{
Console.WriteLine("\nConnected: " + port + "\n");
}
});
}
// Can see port 22 and 80 still?
Parallel.For(1, 100, port =>
{
string host = "scanme.nmap.org";
bool res = TryConnect(host, port, 5000);
if (res)
{
Console.WriteLine("\nConnected: " + port + "\n");
}
});
}
private static bool TryConnect(string strIpAddress, int intPort, int nTimeoutMsec)
{
Socket socket = null;
bool retval = false;
try
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = socket.BeginConnect(strIpAddress, intPort, null, null);
bool success = result.AsyncWaitHandle.WaitOne(nTimeoutMsec, true);
retval = socket.Connected;
}
catch
{
Console.WriteLine("error: " + intPort);
retval = false;
}
finally
{
if (null != socket)
socket.Close();
}
return retval;
}
}
}
I'm trying to write a simple connect port scanner. I'm testing it against the first 10K ports at scanme.nmap.org. It should see ports 22, 80 and 9929. If I scan 1 - 10000 it finds 22 and 80, but doesn't see 9929. If I scan 9900 to 10000 first then 1-10000 (as in the example below) it sees 9929, but often doesn't see port 80 or 22.
I know I could try using WinPcap via a .NET wrapper and go lower level, but is there anyway to get a simple TCP connect port scanner working reliably without WinPcap?
Note: I currently do the scans in batches of 100 because I got even worse results if doing them in bigger chunks.
using System;
using System.Net.Sockets;
using System.Threading.Tasks;
namespace ps
{
internal class Program
{
private const int batchSize = 100;
public static void Main(string[] args)
{
int minPort = Convert.ToInt32(args[0]);
int maxPort = Convert.ToInt32(args[1]);
int loops;
if (maxPort < batchSize)
{
loops = 1;
}
else
{
loops = maxPort/batchSize;
}
// If I look for 9929 in the inital 100 - I can find it
Parallel.For(9900, 10000, port =>
{
string host = "scanme.nmap.org";
bool res = TryConnect(host, port, 5000);
if (res)
{
Console.WriteLine("\nConnected: " + port + "\n");
}
});
// now loop through all ports in batches
// should see 22, 80 & 9929 but normally doesn't
for (int i = 0; i < loops; i++)
{
minPort = 1 + (i*batchSize);
if (loops != 1)
{
maxPort = batchSize + (i*batchSize);
}
Console.WriteLine("minPort:" + minPort + " maxPort:" + maxPort);
Parallel.For(minPort, maxPort, port =>
{
string host = "scanme.nmap.org";
bool res = TryConnect(host, port, 5000);
if (res)
{
Console.WriteLine("\nConnected: " + port + "\n");
}
});
}
// Can see port 22 and 80 still?
Parallel.For(1, 100, port =>
{
string host = "scanme.nmap.org";
bool res = TryConnect(host, port, 5000);
if (res)
{
Console.WriteLine("\nConnected: " + port + "\n");
}
});
}
private static bool TryConnect(string strIpAddress, int intPort, int nTimeoutMsec)
{
Socket socket = null;
bool retval = false;
try
{
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = socket.BeginConnect(strIpAddress, intPort, null, null);
bool success = result.AsyncWaitHandle.WaitOne(nTimeoutMsec, true);
retval = socket.Connected;
}
catch
{
Console.WriteLine("error: " + intPort);
retval = false;
}
finally
{
if (null != socket)
socket.Close();
}
return retval;
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为如果计算循环没有结果的话,你就会有一个差一的情况。
请注意最后一次失败的情况。
I think you have an off-by-one on calculating loops if it doesn't come out even.
Note how all your failures would have been in the last pass.