编写一个端口扫描器(类似nmap的简易版本)。给定目的ip地址,可以扫描目的IP地址在哪个端口上可以接受tcp连接和udp连接。
时间: 2024-02-06 11:11:26 浏览: 206
TCP/UDP端口扫描器的设计(含源码)
4星 · 用户满意度95%
好的,为您提供一个用C++编写的基于Boost.Asio库的TCP和UDP端口扫描器示例代码。代码中使用多线程并发扫描端口,以提高扫描速度。
代码如下:
```cpp
#include <boost/asio.hpp>
#include <thread>
#include <iostream>
#include <vector>
using namespace boost::asio;
// 检查指定端口是否开放
bool check_port(ip::tcp::endpoint& ep) {
io_service ios;
ip::tcp::socket sock(ios);
try {
sock.connect(ep);
} catch (...) {
return false;
}
return true;
}
bool check_port(ip::udp::endpoint& ep) {
io_service ios;
ip::udp::socket sock(ios);
try {
sock.open(ep.protocol());
sock.send_to(buffer(""), ep);
sock.receive_from(buffer(""), ep);
} catch (...) {
return false;
}
return true;
}
// 扫描指定ip地址和端口范围的TCP端口
void scan_tcp_ports(const std::string& ip, int start_port, int end_port, std::vector<int>& result) {
for (int port = start_port; port <= end_port; ++port) {
ip::tcp::endpoint ep(ip::address::from_string(ip), port);
if (check_port(ep)) {
result.push_back(port);
}
}
}
// 扫描指定ip地址和端口范围的UDP端口
void scan_udp_ports(const std::string& ip, int start_port, int end_port, std::vector<int>& result) {
for (int port = start_port; port <= end_port; ++port) {
ip::udp::endpoint ep(ip::address::from_string(ip), port);
if (check_port(ep)) {
result.push_back(port);
}
}
}
// 多线程扫描TCP端口
void scan_tcp_ports_concurrently(const std::string& ip, int start_port, int end_port, std::vector<int>& result, int thread_count) {
std::vector<std::thread> threads;
int step = (end_port - start_port + 1) / thread_count;
for (int i = 0; i < thread_count; ++i) {
int begin = start_port + i * step;
int end = (i == thread_count - 1) ? end_port : begin + step - 1;
threads.emplace_back([ip, begin, end, &result]() {
scan_tcp_ports(ip, begin, end, result);
});
}
for (auto& t : threads) {
t.join();
}
}
// 多线程扫描UDP端口
void scan_udp_ports_concurrently(const std::string& ip, int start_port, int end_port, std::vector<int>& result, int thread_count) {
std::vector<std::thread> threads;
int step = (end_port - start_port + 1) / thread_count;
for (int i = 0; i < thread_count; ++i) {
int begin = start_port + i * step;
int end = (i == thread_count - 1) ? end_port : begin + step - 1;
threads.emplace_back([ip, begin, end, &result]() {
scan_udp_ports(ip, begin, end, result);
});
}
for (auto& t : threads) {
t.join();
}
}
int main(int argc, char* argv[]) {
if (argc < 5) {
std::cerr << "Usage: " << argv[0] << " <ipaddr> <start_port> <end_port> <tcp/udp> [thread_count]\n";
exit(1);
}
std::string ip(argv[1]);
int start_port = std::stoi(argv[2]);
int end_port = std::stoi(argv[3]);
std::string protocol(argv[4]);
int thread_count = (argc == 6) ? std::stoi(argv[5]) : std::thread::hardware_concurrency();
std::vector<int> open_ports;
if (protocol == "tcp") {
scan_tcp_ports_concurrently(ip, start_port, end_port, open_ports, thread_count);
std::cout << "Open TCP Ports:\n";
} else if (protocol == "udp") {
scan_udp_ports_concurrently(ip, start_port, end_port, open_ports, thread_count);
std::cout << "Open UDP Ports:\n";
} else {
std::cerr << "Invalid protocol: " << protocol << std::endl;
exit(1);
}
for (auto port : open_ports) {
std::cout << port << "\n";
}
return 0;
}
```
该程序使用Boost.Asio库实现TCP和UDP连接检查,支持多线程并发扫描端口,以提高扫描速度。
主要分为以下几个函数:
- `check_port` 函数尝试连接给定的 `ip::tcp::endpoint` 或 `ip::udp::endpoint`,如果连接成功,则表示指定端口开放;否则,指定端口被关闭或被防火墙拦截。
- `scan_tcp_ports` 和 `scan_udp_ports` 函数分别循环遍历指定的端口范围,对每个端口调用 `check_port` 函数,如果返回 true,则表示该端口开放,并将其添加到 `result` 向量中。
- `scan_tcp_ports_concurrently` 和 `scan_udp_ports_concurrently` 函数使用多线程并发扫描端口。这两个函数将指定的端口范围平均分成多个子范围,并在每个子范围上启动一个线程执行 `scan_tcp_ports` 或 `scan_udp_ports` 函数。最后,将所有线程的结果合并到 `result` 向量中。
- `main` 函数读取命令行参数,根据指定的协议类型,调用 `scan_tcp_ports_concurrently` 或 `scan_udp_ports_concurrently` 函数扫描指定 IP 地址和端口范围的端口,并将结果打印到屏幕上。
在运行程序时,需要提供以下命令行参数:
```
<ipaddr> <start_port> <end_port> <tcp/udp> [thread_count]
```
其中:
- `ipaddr`:目标 IP 地址。
- `start_port` 和 `end_port`:扫描的端口范围。
- `tcp` 或 `udp`:指定要扫描的协议类型。
- `thread_count`:可选参数,指定使用的线程数。如果未指定,则使用计算机的 CPU 核心数。
希望这个示例代码能够帮助您编写一个简单的端口扫描器。
阅读全文