当前位置: 首页 > news >正文

UDP端口可达性检测(端口扫描)工具开发

UDP端口可达性检测(端口扫描)工具开发

1、应用场景分析

主机X主机Y部署在AB双网环境下,两个主机间通过UDP协议进行数据交互。应用程序发送数据时,优先使用A网发送数据,如果A网异常则通过B网发送数据。两个主机应用间没有设置心跳帧 ,所以无法检测到对方UDP端口是否可达。

在这里插入图片描述

场景诉求

主机间发送UDP数据前,应能检测对方端口是否可达。如果不可达,则进行A/B网切换。达到动态检测对方网络服务端口状态,实时切换网络链路效果。

①、 主机不可达

场景分析:

  • 主机关机。
  • 防火墙开启策略。
  • 网卡故障、网线连接异常。
  • 网络配置错误。

场景应对策略:

通过PING echo 判断主机是否可达。

②、 端口不可达

主机可达,端口不可达。

场景分析:

  • 服务未启动,端口未监听。
  • 防火墙开启策略。

场景应对策略:

结合ICMP和内核网络协议栈,判断UDP端口是否可达。

2、UDP端口扫描程序开发

①、Windows程序

【1】、 理论知识

略。

【2】、 C++源码

界面控件设计。

在这里插入图片描述

对话框初始化部分代码。

BOOL CUdpDetectDlg::OnInitDialog()
{CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);			// 设置大图标SetIcon(m_hIcon, FALSE);		// 设置小图标// 初始化Windows套接字WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){CString strMsg;strMsg.Format("WSAStartup失败!");return 0;}// CListCtrlDWORD dwStyle = m_ListCtrl.GetExtendedStyle();m_ListCtrl.SetExtendedStyle(dwStyle | LVS_EX_FULLROWSELECT );m_ListCtrl.InsertColumn(0, _T("主机端口"), LVCFMT_LEFT, 130);m_ListCtrl.InsertColumn(1, _T("扫描结果"), LVCFMT_LEFT, 100);m_ListCtrl.InsertColumn(2, _T("ICMP反馈"), LVCFMT_LEFT, 350);// 默认参数;m_EditScanHostIP.SetWindowText("192.168.58.1");m_EditScanPortStartNo.SetWindowText("50000");m_EditScanEndPortNo.SetWindowText("50005");return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

端口扫描部分代码。

//扫描端口;
void CUdpDetectDlg::ScanPort()
{CString strScanHost;m_EditScanHostIP.GetWindowText(strScanHost);CString strScanStartPort;m_EditScanPortStartNo.GetWindowText(strScanStartPort);CString strScanEndPort;m_EditScanEndPortNo.GetWindowText(strScanEndPort);int iStartPort = _ttoi(strScanStartPort);int iEndPort = _ttoi(strScanEndPort);if (iEndPort < iStartPort)  return;m_ListCtrl.DeleteAllItems();for (int ii = iStartPort; ii <= iEndPort;++ii){BOOL isPortOpenF = FALSE;char szErrText[256] = { 0 };sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);if (sock < 0) return;//设置收发缓冲区大小;int iTemp = 1024 * 2;setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&iTemp, sizeof(iTemp));setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&iTemp, sizeof(iTemp));//设置接收超时;int iRecvTimeout = 1000;setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&iRecvTimeout, sizeof(iRecvTimeout));struct sockaddr_in txaddr;txaddr.sin_family = AF_INET;txaddr.sin_addr.s_addr = inet_addr(strScanHost.GetBuffer(0));txaddr.sin_port = htons(ii);int addrlen = sizeof(txaddr);char txbuff[] = "";int txlen = sendto(sock, txbuff, sizeof(txbuff), 0, (sockaddr*)&txaddr, addrlen);char rxbuff[24] = { 0 };int rxlen = recvfrom(sock, rxbuff, 24, 0, (sockaddr*)&txaddr, &addrlen);if (rxlen < 0){if (WSAGetLastError() == WSAECONNRESET){FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,NULL, WSAECONNRESET, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),szErrText, 256, NULL);isPortOpenF = FALSE;}elseisPortOpenF = TRUE;}CString strHostDesc;strHostDesc.Format("%s:%d", strScanHost, ii);CString strPortState;if (isPortOpenF)strPortState.Format("端口可达");elsestrPortState.Format("端口不可达");int iIndex = m_ListCtrl.GetItemCount();m_ListCtrl.InsertItem(iIndex, strHostDesc);m_ListCtrl.SetItemText(iIndex, 1, strPortState);m_ListCtrl.SetItemText(iIndex, 2, CString(szErrText));closesocket(sock);}
}
【3】、 编译程序

在这里插入图片描述

【4】、 运行程序

先将目标主机的50001端口开启监听。然后用测试程序检测。

在这里插入图片描述

开始扫描端口。

在这里插入图片描述

②、 Linux程序

【1】、 理论知识

略。

【2】、 C++源码

UdpScan.cxx

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string>
#include<algorithm>int main()
{printf("*********************************************************************\n");printf("*                                                                   *\n");printf("*                      Linux 端口扫描工具 V0.1                       *\n");printf("*                                                                   *\n");printf("*********************************************************************\n");printf("请输入扫描主机IP地址: ");char input[256] = {0};char* ptr = fgets(input,256,stdin);if(ptr == nullptr) { printf("输入参数异常,结束程序!\n"); }std::string strHost = std::string(ptr);printf("请输入扫描UDP端口范围(比如2000-2500): ");ptr = fgets(input,256,stdin);if(ptr == nullptr) { printf("输入参数异常,结束程序!\n"); }std::string strPort = std::string(ptr);int iStartPort = 0, iEndPort = 0;int pos = strPort.find("-");if(pos != std::string::npos){std::string strStartPort = strPort.substr(0,pos);std::string strEndPort = strPort.substr(pos+1);iStartPort = std::stoi(strStartPort);iEndPort = std::stoi(strEndPort);}if(iEndPort < iStartPort) return 1;for(int ii = iStartPort; ii <= iEndPort; ++ ii){   int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);//将ICMP端口不可达信息报到应用层协议int flag = 1; setsockopt(sock, IPPROTO_IP, IP_RECVERR , &flag,sizeof(int)); //设置接收超时struct timeval timeout = {0,300};setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr(strHost.c_str());addr.sin_port = htons(ii);char txbuff[] = ""; int ret = sendto(sock,txbuff,sizeof(txbuff),0,(struct sockaddr*)&addr,sizeof(addr)); char rxbuff[24] = { 0 };int addrlen = sizeof(addr);int rxlen = recvfrom(sock, rxbuff, sizeof(rxbuff), 0, (struct sockaddr *)&addr, &addrlen);if (rxlen == -1){//剔除回车符strHost.erase(std::remove(strHost.begin(), strHost.end(), '\n'), strHost.end());if (errno == ECONNREFUSED){printf("主机【%s:%d】端口不可达!\n",strHost.c_str(),ii);}elseprintf("主机【%s:%d】端口可达!\n",strHost.c_str(),ii);} close(sock);}printf("端口扫描结束!\n");return 0;
}

代码截图:

在这里插入图片描述

在这里插入图片描述

【3】、 编译程序
g++ -o udpscan UdpScan.cxx -fpermissive -std=c++11 -w -W
【4】、 运行程序

先将目标主机的50001端口开启监听。然后用测试程序检测。

在这里插入图片描述

开始扫描端口。

在这里插入图片描述

http://www.lryc.cn/news/417935.html

相关文章:

  • 第三届计算、通信、感知与量子技术国际会议(CCPQT 2024)会议通知
  • Qt文件读写
  • 发现了一套超厉害的英语资料,绝对YYDS
  • C# new关键字作用
  • Python代码之特征工程基础
  • 低代码平台:效率利器还是质量妥协?
  • 大数据-Big Data
  • Redis的持久化的策略
  • 【八】Zookeeper3.7.1集成Hadoop3.3.4集群安装
  • 【C/C++笔记】:易错难点3 (二叉树)
  • 一篇文章解决Webpack
  • 速盾:cdn如何解析php文件中的图片?
  • 如何快速实现MODBUS TCP转Profinet——泗博网关EPN-330
  • 什么是实时数据仓库?它有哪些不可替代之处?
  • 《Ubuntu22.04环境下的ROS2学习笔记1》
  • Jupyter nbextensions安装与使用
  • java.nio.charset.MalformedInputException: Input length = 1
  • yarn的安装和配置使用
  • JVM知识总结(即时编译)
  • 【网络】TCP协议——TCP连接相关、TCP连接状态相关、TCP数据传输与控制相关、TCP数据处理和异常、基于TCP应用层协议
  • 一起看看JavaAgent到底是干啥用的
  • k8s工作负载控制器--DaemonSet
  • 探索Python文档自动化的奥秘:MkDocs的神奇之旅
  • 树莓派边缘计算网关搭建:集成MQTT、SQLite与Flask的完整解决方案
  • 如何通过GD32 MCU内部ADC参考电压通道提高采样精度?
  • Centos安装OpenSearch
  • 【pkill pgrep】Centos/Linux pkill命令详细介绍
  • Java如何使用 HTTP 请求下载图片
  • ARM/Linux嵌入式面经(二十):地平线嵌入式开发
  • 无人机竞速赛