做外贸常用那几个网站,网络工程师主要做什么,做网站需要什么开发语言,免费有趣的网址端口扫描是一种用于识别目标系统上哪些网络端口处于开放、关闭或监听状态的网络活动。在计算机网络中#xff0c;端口是一个虚拟的通信端点#xff0c;用于在计算机之间传输数据。每个端口都关联着特定类型的网络服务或应用程序。端口扫描通常是网络管理员、安全专业人员用来…端口扫描是一种用于识别目标系统上哪些网络端口处于开放、关闭或监听状态的网络活动。在计算机网络中端口是一个虚拟的通信端点用于在计算机之间传输数据。每个端口都关联着特定类型的网络服务或应用程序。端口扫描通常是网络管理员、安全专业人员用来评估网络安全的一种方法。通过扫描目标系统的端口可以了解系统上哪些服务在运行、哪些端口是开放的从而评估系统的安全性。
常见的端口扫描技术包括
TCP端口扫描 通过发送TCP连接请求来确定目标系统上的端口是否开放。常见的TCP扫描包括全连接扫描Connect Scan、半开放扫描SYN Scan等。UDP端口扫描 通过向目标系统发送UDP数据包观察是否收到相应来判断UDP端口是否开放。UDP扫描较为复杂因为UDP是一种无连接的协议难以确定是否因为端口关闭而未响应。NULL、FIN和Xmas Tree扫描 这些扫描技术利用TCP协议的特殊性质尝试向目标系统发送非法或异常的TCP数据包观察目标系统的响应。IDLE扫描 利用一个第三方系统通常是僵尸主机发送探测包通过观察目标系统的响应来判断端口状态。这种扫描方法更难被目标系统检测到。
本章我们将运用Boost框架实现一个基于TCP的扫描工具TCP端口扫描是一种常见的网络扫描技术通过发送TCP连接请求来确定目标系统上的端口是否开放其本质上是通过调用Socket套接字中的connect()尝试连接对应的端口如果该端口开放则连接将被建立由此我们就可以得出该端口是存活的利用这一特性我们就可以实现批量的端口探测功能。
生成C段地址
C段地址通常指的是IPv4地址中的子网地址其中C表示了地址的网络前缀的类别。IPv4地址按照其前缀的长度被分为A、B、C、D和E五个类别每个类别用于不同规模的网络。
在IPv4地址中每个地址由32位二进制数字组成通常以点分十进制Dotted-Decimal Notation的形式表示例如192.168.0.1。IPv4地址的前面的一部分被分配给网络而后面的部分则分配给主机。
A类地址 以0开头用于大型网络例如1.0.0.0到126.0.0.0。B类地址 以10开头用于中型网络例如128.0.0.0到191.255.0.0。C类地址 以110开头用于小型网络例如192.0.0.0到223.255.255.0。
因此当我们说一个IPv4地址属于C段地址时通常指的是这个地址的前缀是C类地址的范围即以192.x.x.x到223.x.x.x的范围。例如192.168.1.1是一个C段地址因为它的前缀是192。在这样的地址中最后三个字节通常用于主机标识。
同样我们在实现端口扫描之前需要生成一个C段地址中所有的主机IP这里我们可以通过Boost库中的字符串拼接功能来实现生成特定主机网段具体实现细节如下所示
例如192.168.1.1/100则代表要枚举出这个网段中所有的地址并将其存储到std::vectorstd::string容器中。
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include iostream
#include vector
#include boost/format.hpp
#include boost/lexical_cast.hpp
#include boost/algorithm/string.hppusing namespace std;
using namespace boost;// 传递IP地址范围,自动生成IP地址表
bool CalculationAddress(std::string address, std::vectorstd::string ref)
{std::vectorstd::string vect;try{// 以/,两个下划线作为切割符号,切割后放入vect容器中boost::split(vect, address, boost::is_any_of(/) || boost::is_any_of(.), boost::token_compress_on);// 将开始和结束地址取出来int start_count lexical_castint(vect[3]);int end_count lexical_castint(vect[4]);// IP地址中的C段必须小于255if (end_count 255){for (int x start_count; x end_count; x){std::string this_address boost::str(boost::format(%s.%s.%s.%s) % vect[0] % vect[1] % vect[2] % x);ref.push_back(this_address);}}else{return false;}}catch (...){return false;}return true;
}int main(int argc, char * argv[])
{// 生成 192.168.1.1/100 这个范围内的地址表std::vectorstd::string address_ref;bool flag CalculationAddress(192.168.1.1/255, address_ref);if (flag true){// 输出地址表for (int x 0; x address_ref.size(); x){std::cout 地址表: address_ref[x] std::endl;}}std::system(pause);return 0;
}上述函数CalculationAddress通过传入范围192.168.1.1/100即可实现生成1-100以内的所有IP地址字符串并将其存储到address_ref容器内输出效果如下图所示 端口字符串提取
接着我们还需要实现一个提取端口字符串的功能例如当使用者传入22,23,135,139时我们将其解析成独立的整数类型并将其存储到std::vectorint容器内保存该功能的实现只需要使用boost::split函数切割并循环将数据放入到整数容器内即可如下所示
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include iostream
#include vector
#include boost/format.hpp
#include boost/lexical_cast.hpp
#include boost/algorithm/string.hppusing namespace std;
using namespace boost;// 传递端口字符串,解析为vector容器
bool CalculationPort(std::string port_string, std::vectorint ref)
{std::vectorstd::string vect;try{boost::split(vect, port_string, boost::is_any_of(,), boost::token_compress_on);for (int x 0; x vect.size(); x){ref.push_back(lexical_castint(vect[x]));}return true;}catch (...){return false;}return true;
}int main(int argc, char * argv[])
{// 传入字符串端口,自动解析为vector容器std::vectorint port_ref;bool flag CalculationPort(22,23,55,135, port_ref);if (flag true){// 输出地址表for (int x 0; x port_ref.size(); x){std::cout 端口表: port_ref[x] std::endl;}}std::system(pause);return 0;
}通过boost中的函数可以很容易实现字符串的切割运行后可看到字符串被解析成了独立的整数如下图所示 异步端口探测
Boost.Asio是一个强大的C库提供了异步I/O和网络编程的支持。本文将介绍如何使用Boost.Asio实现异步连接以及如何设置超时机制确保连接在规定的时间内建立。Asio是Boost库中的一个模块用于异步I/O和网络编程。它提供了一种灵活的方式来处理异步操作使得程序能够更高效地利用系统资源。Boost.Asio支持TCP、UDP、SSL等协议使得开发者能够轻松实现异步网络通信。
异步连接实现
在本文的代码示例中我们使用Boost.Asio创建了一个AsyncConnect类用于执行异步连接。这个类包含了异步连接的主要逻辑其中使用了tcp::socket和deadline_timer来处理异步操作和超时。
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include iostream
#include string
#include boost/asio.hpp
#include boost/bind.hpp
#include boost/date_time/posix_time/posix_time_types.hpp using namespace std;
using boost::asio::ip::tcp;// 异步连接地址与端口
class AsyncConnect
{
public:AsyncConnect(boost::asio::io_service ios, tcp::socket s):io_service_(ios), timer_(ios), socket_(s) {}// 异步连接bool aysnc_connect(const tcp::endpoint ep, int million_seconds){bool connect_success false;// 异步连接,当连接成功后将触发 connect_handle 函数socket_.async_connect(ep, boost::bind(AsyncConnect::connect_handle, this, _1, boost::ref(connect_success)));// 设置一个定时器 million_seconds timer_.expires_from_now(boost::posix_time::milliseconds(million_seconds));bool timeout false;// 异步等待 如果超时则执行 timer_handletimer_.async_wait(boost::bind(AsyncConnect::timer_handle, this, _1, boost::ref(timeout)));do{// 等待异步操作完成io_service_.run_one();// 判断如果timeout没超时,或者是连接建立了,则不再等待} while (!timeout !connect_success);timer_.cancel();return connect_success;}private:// 如果连接成功了,则 connect_success truevoid connect_handle(boost::system::error_code ec, bool connect_success){if (!ec){connect_success true;}}// 定时器超时timeout truevoid timer_handle(boost::system::error_code ec, bool timeout){if (!ec){socket_.close();timeout true;}}boost::asio::io_service io_service_;boost::asio::deadline_timer timer_;tcp::socket socket_;
};探测主函数
在主函数中我们创建了一个AsyncConnect对象并使用它进行异步连接。这个例子中我们尝试连接到IP地址为202.89.233.101端口号为80的服务器并设置了连接超时时间为300毫秒。
int main(int argc, char * argv[])
{try{boost::asio::io_service io;tcp::socket socket(io);AsyncConnect hander(io, socket);tcp::endpoint ep(boost::asio::ip::address::from_string(8.141.58.64), 80);// 传递扫描ep地址结构,以及超时时间if (hander.aysnc_connect(ep, 300)){std::cout 连通了 std::endl;io.run();}else{std::cout 连接失败 std::endl;}}catch (...){return false;}std::system(pause);return 0;
}通过本文的示例我们展示了如何使用Boost.Asio创建异步连接并设置连接超时。异步连接的实现可以提高程序的性能和效率特别适用于需要处理大量并发连接的网络应用场景。Boost.Asio的灵活性使得开发者能够更方便地处理异步I/O操作提高程序的健壮性和可维护性。
当代码被运行时则自动探测特定地址的特定端口是否开放如果开放则返回如下图所示 端口扫描封装
实现端口扫描
首先增加PortScan函数该函数传入地址端口号以及超时时间自动扫描端口开放状态这里我们就以扫描192.168.1.1端口从78-100扫描后将结果输出到屏幕上。
// 封装端口扫描函数
bool PortScan(std::string address, int port, int timeout)
{try{boost::asio::io_service io;tcp::socket socket(io);AsyncConnect hander(io, socket);tcp::endpoint ep(boost::asio::ip::address::from_string(address), port);// 传递扫描ep地址结构,以及超时时间if (hander.aysnc_connect(ep, timeout)){io.run();return true;}else{return false;}}catch (...){return false;}
}int main(int argc, char * argv[])
{for (int x 78; x 100; x){bool is_open PortScan(192.168.1.1, x, 1000);std::cout 扫描端口: x 状态: is_open std::endl;}std::system(pause);return 0;
}运行上述代码即可扫描特定的端口是否开放输出效果如下图所示 实现特定端口扫描
实现CalculationPort函数用户传入一串字符串自动解析为端口号并调用扫描功能对特定端口进行扫描。
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include iostream
#include string
#include boost/asio.hpp
#include boost/bind.hpp
#include boost/date_time/posix_time/posix_time_types.hpp#include boost/format.hpp
#include boost/lexical_cast.hpp
#include boost/algorithm/string.hppusing namespace std;
using namespace boost;
using boost::asio::ip::tcp;// 传递端口字符串,解析为vector容器
bool CalculationPort(std::string port_string, std::vectorint ref)
{std::vectorstd::string vect;try{boost::split(vect, port_string, boost::is_any_of(,), boost::token_compress_on);for (int x 0; x vect.size(); x){ref.push_back(lexical_castint(vect[x]));}return true;}catch (...){return false;}return true;
}int main(int argc, char * argv[])
{std::string scan_address 192.168.1.1;std::vectorint scan_port_list;bool scan_ref CalculationPort(80,443,445,135,139, scan_port_list);if (scan_ref true){// 循环取出需要扫描的端口对目标进行扫描for (int x 0; x scan_port_list.size(); x){bool is_open PortScan(scan_address, scan_port_list[x], 1000);if (is_open true){std::cout 扫描地址: scan_address 扫描端口: scan_port_list[x] 扫描状态: 端口开放 std::endl;}else{std::cout 扫描地址: scan_address 扫描端口: scan_port_list[x] 扫描状态: 端口关闭 std::endl;}}}std::system(pause);return 0;
}运行上述代码即可扫描地址192.168.1.1下的80,443,445,135,139端口开放状态如下图所示 增加参数解析
Boost Program Options 是Boost库中的一个模块用于处理程序的命令行选项。它提供了一个灵活的框架使得开发者能够轻松地解析和处理命令行参数。
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include iostream
#include string
#include boost/asio.hpp
#include boost/bind.hpp
#include boost/date_time/posix_time/posix_time_types.hpp#include boost/format.hpp
#include boost/lexical_cast.hpp
#include boost/algorithm/string.hpp#include boost/program_options.hppusing namespace std;
using namespace boost;
using boost::asio::ip::tcp;
namespace opt boost::program_options;int main(int argc, char * argv[])
{opt::options_description des_cmd(\n Usage: LyShark 端口扫描器 Ver:1.0 \n\n Options);des_cmd.add_options()(address,a, opt::valuestd::string()-default_value(127.0.0.1), 指定扫描地址)(set_port,s, opt::valuestd::string()-default_value(none), 设置扫描端口)(help,h, 帮助菜单);opt::variables_map virtual_map;try{opt::store(opt::parse_command_line(argc, argv, des_cmd), virtual_map);}catch (...){ return 0; }// 定义消息opt::notify(virtual_map);// 无参数直接返回if (virtual_map.empty()){return 0;}else if (virtual_map.count(help) || virtual_map.count(h)){std::cout des_cmd std::endl;return 0;}else if (virtual_map.count(address) virtual_map.count(set_port)){std::string address virtual_map[address].asstd::string();std::string set_port virtual_map[set_port].asstd::string();// 判断是不是默认参数if (address 127.0.0.1 || set_port none){std::cout des_cmd std::endl;}else{// 执行扫描流程std::vectorint scan_port_list;bool scan_ref CalculationPort(set_port, scan_port_list);if (scan_ref true){// 循环取出需要扫描的端口对目标进行扫描for (int x 0; x scan_port_list.size(); x){bool is_open PortScan(address, scan_port_list[x], 1000);if (is_open true){std::cout 扫描地址: address 扫描端口: scan_port_list[x] 扫描状态: 端口开放 std::endl;}else{std::cout 扫描地址: address 扫描端口: scan_port_list[x] 扫描状态: 端口关闭 std::endl;}}}}}else{std::cout 参数错误 std::endl;}return 0;std::system(pause);return 0;
}当有了命令解析功能我们就可以向程序内传入参数如下所示 多线程扫描
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include iostream
#include string
#include boost/asio.hpp
#include boost/bind.hpp
#include boost/date_time/posix_time/posix_time_types.hpp#include boost/format.hpp
#include boost/lexical_cast.hpp
#include boost/algorithm/string.hpp#include boost/program_options.hpp#include boost/bind.hpp
#include boost/thread.hpp
#include boost/function.hpp
#include boost/thread/thread_guard.hppusing namespace std;
using namespace boost;
using boost::asio::ip::tcp;
namespace opt boost::program_options;boost::mutex io_mutex;// 实现多线程扫描
void MyThread(std::string address, int port)
{bool is_open PortScan(address, port, 1000);// boost::mutex::scoped_lock lock(io_mutex);boost::lock_guardboost::mutex global_mutex(io_mutex);if (is_open true){std::cout 扫描地址: address 扫描端口: port 扫描状态: 开放 std::endl;}else{std::cout 扫描地址: address 扫描端口: port 扫描状态: 关闭 std::endl;}
}int main(int argc, char * argv[])
{opt::options_description des_cmd(\n Usage: LyShark 端口扫描器 Ver:1.0 \n\n Options);des_cmd.add_options()(address,a, opt::valuestd::string()-default_value(127.0.0.1), 指定扫描地址)(set_port,s, opt::valuestd::string()-default_value(none), 设置扫描端口)(help,h, 帮助菜单);opt::variables_map virtual_map;try{opt::store(opt::parse_command_line(argc, argv, des_cmd), virtual_map);}catch (...){ return 0; }// 定义消息opt::notify(virtual_map);// 无参数直接返回if (virtual_map.empty()){return 0;}else if (virtual_map.count(help) || virtual_map.count(h)){std::cout des_cmd std::endl;return 0;}else if (virtual_map.count(address) virtual_map.count(set_port)){std::string address virtual_map[address].asstd::string();std::string set_port virtual_map[set_port].asstd::string();// 判断是不是默认参数if (address 127.0.0.1 || set_port none){std::cout des_cmd std::endl;}else{// 执行扫描流程std::vectorint scan_port_list;bool scan_ref CalculationPort(set_port, scan_port_list);if (scan_ref true){boost::thread_group group;// 循环取出需要扫描的端口对目标进行扫描for (int x 0; x scan_port_list.size(); x){group.create_thread(boost::bind(MyThread, address, scan_port_list[x]));}group.join_all();}}}else{std::cout 参数错误 std::endl;}return 0;std::system(pause);return 0;
}运行效果如下图所示通过使用多线程可提高程序的扫描效率。 完整扫描器代码
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include iostream
#include string
#include boost/asio.hpp
#include boost/bind.hpp
#include boost/date_time/posix_time/posix_time_types.hpp#include boost/format.hpp
#include boost/lexical_cast.hpp
#include boost/algorithm/string.hpp#include boost/program_options.hpp#include boost/bind.hpp
#include boost/thread.hpp
#include boost/function.hpp
#include boost/thread/thread_guard.hppusing namespace std;
using namespace boost;
using boost::asio::ip::tcp;
namespace opt boost::program_options;boost::mutex io_mutex;void ShowOpt()
{fprintf(stderr,# # # \n# # # \n# # # ##### ###### ###### # ### # ## \n# # # # # # # # ## # # \n# # # #### # # # # # ### \n# ##### # # # # ## # # # \n##### # ##### # # #### # # # ## \n\n);
}// 异步连接地址与端口
class AsyncConnect
{
public:AsyncConnect(boost::asio::io_service ios, tcp::socket s):io_service_(ios), timer_(ios), socket_(s) {}// 异步连接bool aysnc_connect(const tcp::endpoint ep, int million_seconds){bool connect_success false;// 异步连接,当连接成功后将触发 connect_handle 函数socket_.async_connect(ep, boost::bind(AsyncConnect::connect_handle, this, _1, boost::ref(connect_success)));// 设置一个定时器 million_seconds timer_.expires_from_now(boost::posix_time::milliseconds(million_seconds));bool timeout false;// 异步等待 如果超时则执行 timer_handletimer_.async_wait(boost::bind(AsyncConnect::timer_handle, this, _1, boost::ref(timeout)));do{// 等待异步操作完成io_service_.run_one();// 判断如果timeout没超时,或者是连接建立了,则不再等待} while (!timeout !connect_success);timer_.cancel();return connect_success;}private:// 如果连接成功了,则 connect_success truevoid connect_handle(boost::system::error_code ec, bool connect_success){if (!ec){connect_success true;}}// 定时器超时timeout truevoid timer_handle(boost::system::error_code ec, bool timeout){if (!ec){socket_.close();timeout true;}}boost::asio::io_service io_service_;boost::asio::deadline_timer timer_;tcp::socket socket_;
};// 封装端口扫描函数
bool PortScan(std::string address, int port, int timeout)
{try{boost::asio::io_service io;tcp::socket socket(io);AsyncConnect acHandler(io, socket);tcp::endpoint ep(boost::asio::ip::address::from_string(address), port);// 传递扫描ep地址结构,以及超时时间if (acHandler.aysnc_connect(ep, timeout)){io.run();return true;}else{return false;}}catch (...){return false;}
}// 传递IP地址范围,自动生成IP地址表
bool CalculationAddress(std::string address, std::vectorstd::string ref)
{std::vectorstd::string vect;try{// 以/,两个下划线作为切割符号,切割后放入vect容器中boost::split(vect, address, boost::is_any_of(/) || boost::is_any_of(.), boost::token_compress_on);// 将开始和结束地址取出来int start_count lexical_castint(vect[3]);int end_count lexical_castint(vect[4]);// IP地址中的C段必须小于255if (end_count 255){for (int x start_count; x end_count; x){std::string this_address boost::str(boost::format(%s.%s.%s.%s) % vect[0] % vect[1] % vect[2] % x);ref.push_back(this_address);}}else{return false;}}catch (...){return false;}return true;
}// 传递端口字符串,解析为vector容器
bool CalculationPort(std::string port_string, std::vectorint ref)
{std::vectorstd::string vect;try{boost::split(vect, port_string, boost::is_any_of(,), boost::token_compress_on);for (int x 0; x vect.size(); x){ref.push_back(lexical_castint(vect[x]));}return true;}catch (...){return false;}return true;
}// 实现多线程扫描
void MyThread(std::string address, int port)
{bool is_open PortScan(address, port, 1000);// boost::mutex::scoped_lock lock(io_mutex);boost::lock_guardboost::mutex global_mutex(io_mutex);if (is_open true){std::cout 扫描地址: address 扫描端口: port 扫描状态: 开放 std::endl;}else{std::cout 扫描地址: address 扫描端口: port 扫描状态: 关闭 std::endl;}
}// 实现全端口线程扫描
void MyThreadB(std::string address, int port)
{bool is_open PortScan(address, port, 1000);// boost::mutex::scoped_lock lock(io_mutex);boost::lock_guardboost::mutex global_mutex(io_mutex);if (is_open true){std::cout 扫描地址: address 扫描端口: port 扫描状态: 开放 std::endl;}
}int main(int argc, char * argv[])
{opt::options_description des_cmd(\n Usage: LyShark 端口扫描器 Ver:1.1 \n\n Options);des_cmd.add_options()(address,a, opt::valuestd::string(), 指定扫描地址 192.168.1.1)(c_address,c, opt::valuestd::string(), 设置扫描C地址段 192.168.1.1/24)(set_port,s, opt::valuestd::string(), 设置扫描端口 80,443,135,139)(type,t, opt::valuestd::string(), 对特定主机 扫描 1-65535 全端口)(help,h, 帮助菜单);opt::variables_map virtual_map;try{opt::store(opt::parse_command_line(argc, argv, des_cmd), virtual_map);}catch (...){ return 0; }// 定义消息opt::notify(virtual_map);// 无参数直接返回if (virtual_map.empty()){ShowOpt();std::cout des_cmd std::endl;return 0;}else if (virtual_map.count(help) || virtual_map.count(h)){ShowOpt();std::cout des_cmd std::endl;return 0;}// 扫描全端口else if (virtual_map.count(address) virtual_map.count(type)){std::string address virtual_map[address].asstd::string();std::string type virtual_map[type].asstd::string();if (address.length() ! 0 type all){// 执行全端口扫描boost::thread_group group;for (int x 0; x 65534; x){group.create_thread(boost::bind(MyThreadB, address, x));_sleep(50);}group.join_all();}}// 扫描特定端口else if (virtual_map.count(address) virtual_map.count(set_port)){std::string address virtual_map[address].asstd::string();std::string set_port virtual_map[set_port].asstd::string();// 执行特定端口扫描std::vectorint scan_port_list;bool scan_ref CalculationPort(set_port, scan_port_list);if (scan_ref true){boost::thread_group group;// 循环取出需要扫描的端口对目标进行扫描for (int x 0; x scan_port_list.size(); x){group.create_thread(boost::bind(MyThread, address, scan_port_list[x]));}group.join_all();}}// 扫描特定地址段中的特定端口else if (virtual_map.count(c_address) virtual_map.count(set_port)){std::string c_address virtual_map[c_address].as std::string ();std::string set_port virtual_map[set_port].asstd::string();// 计算出需要扫描的端口std::vectorint scan_port_list;bool scan_port_ref CalculationPort(set_port, scan_port_list);// 计算出需要扫描的地址段std::vector std::string scan_address_list;bool scan_address_ref CalculationAddress(c_address, scan_address_list);if (scan_port_ref true scan_address_ref true){// 分别取出每一个IP地址for (int x 0; x scan_address_list.size(); x){boost::thread_group group;// 对每一个IP地址中的端口段进行扫描for (int y 0; y scan_port_list.size(); y){group.create_thread(boost::bind(MyThreadB, scan_address_list[x], scan_port_list[y]));}group.join_all();}}}else{std::cout 参数错误 std::endl;}return 0;
}至此一个基于ASIO异步模型的多线程端口扫描器就这么完成了总结帮助手册。 扫描全端口: lyscanner.exe --address 192.168.1.1 --type all扫描整个C段: lyscanner.exe --c_address 192.168.1.1/10 --set_port 22,25特定端口扫描: lyscanner.exe --address 192.168.1.1 --set_port 22,25,135,139