1、下载portSentry源码
网址:https://sourceforge.net/projects/sentrytools/files/latest/download
2、解压
3、 make linux
报错, 将图下的printf换行删除。
4、再次make linux;make install
安装路径:
/usr/local/psionic/portsentry
配置文件:
/usr/local/psionic/portsentry/portsentry.conf
记录允许合法扫描服务器的主机地址
/usr/local/psionic/portsentry/portsentry.ignore
入侵主机的IP历史记录
/usr/local/psionic/portsentry/portsentry.history
被阻止连接主机的ip记录
/usr/local/psionic/portsentry/portsentry.blocked
portsentry启动检测模试
portsentry -tcp ---->TCP的基本端口绑定模式
portsentry -udp --->UDP的基本端口绑定模式
portsentry -stcp --->TCP的秘密扫描模式
portsentry -sudp --->UDP的秘密扫描检测模式
portsentry -atcp ---->TCP的高级秘密扫描检测模式
portsentry audp ----->UDP的高级秘密扫描检测
启动:
./portsentry -atcp
portsentry.conf文件中会存储检测的端口号,可通过修改此处的端口进行配置。
当有设备对本机进行端口扫描时,portsentry.history会进行IP记录。
参考:
https://www.cnblogs.com/bass6/p/5979091.html?utm_source=itdadao&utm_medium=referral
https://www.cnblogs.com/chenguang/p/3742442.html
抽取portsentry源码结合iptables对机器做防御:
#ifndef _OAMDEFENSE_H_
#define _OAMDEFENSE_H_
/********************
*本程序主要做ECS节点的防御
********************/
#include "common.h"
#include "cJSON.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#ifndef _NETINET_TCP_H
#define _NETINET_TCP_H 1
#include <features.h>
__BEGIN_DECLS
struct tcphdr
{
u_int16_t source;
u_int16_t dest;
u_int32_t seq;
u_int32_t ack_seq;
#if __BYTE_ORDER == __LITTLE_ENDIAN
u_int16_t res1 : 4;
u_int16_t doff : 4;
u_int16_t fin : 1;
u_int16_t syn : 1;
u_int16_t rst : 1;
u_int16_t psh : 1;
u_int16_t ack : 1;
u_int16_t urg : 1;
u_int16_t res2 : 2;
#elif __BYTE_ORDER == __BIG_ENDIAN
u_int16_t doff : 4;
u_int16_t res1 : 4;
u_int16_t res2 : 2;
u_int16_t urg : 1;
u_int16_t ack : 1;
u_int16_t psh : 1;
u_int16_t rst : 1;
u_int16_t syn : 1;
u_int16_t fin : 1;
#else
#error "Adjust your <bits/endian.h> defines"
#endif
u_int16_t window;
u_int16_t check;
u_int16_t urg_ptr;
};
#endif /* tcp.h */
#ifndef __NETINET_IP_H
#define __NETINET_IP_H 1
struct iphdr
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
u_int8_t ihl : 4;
u_int8_t version : 4;
#elif __BYTE_ORDER == __BIG_ENDIAN
u_int8_t version : 4;
u_int8_t ihl : 4;
#else
#error "Please fix <bytesex.h>"
#endif
u_int8_t tos;
u_int16_t tot_len;
u_int16_t id;
u_int16_t frag_off;
u_int8_t ttl;
u_int8_t protocol;
u_int16_t check;
u_int32_t saddr;
u_int32_t daddr;
/*The options start here. */
};
#endif
#ifndef __NETINET_UDP_H
#define __NETINET_UDP_H 1
__BEGIN_DECLS
/* UDP header as specified by RFC 768, August 1980. */
struct udphdr {
u_int16_t source;
u_int16_t dest;
u_int16_t len;
u_int16_t check;
};
__END_DECLS
#endif /* netinet/udp.h */
/* max sockets we can open */
#define MAXSOCKS 64
/* max size of an IP address plus NULL */
#define IPMAXBUF 16
#define TCPPACKETLEN 80
#define DNSMAXBUF 255
#define UDPPACKETLEN 68
#define TRUE 1
#define FALSE 0
#define ERROR -1
/*端口配置文件*/
const char CONFIG_FILE[MIDLEN] = "/root/oamMidWare/oamDefense.conf";
/*日志文件*/
const char LOGFILE[MIDLEN] = "/root/oamMidWare/log/oamDefense.log";
const char GLOBAL_ATTACK_LOG_FILE_PATH[MIDLEN] = "/var/log/attack.log";
void thread_portSentryTCP(void);
void thread_portSentryUDP(void);
int MonitorStealthModeTCP();
int MonitorStealthModeUDP();
int ConfigTokenRetrieve(char* token, char* configToken);
char* SafeStrncpy(char* dest, const char* src, size_t size);
int OpenTCPSocket(void);
int OpenUDPSocket(void);
int BindSocket(int sockfd, struct sockaddr_in client, struct sockaddr_in server, int port);
int OpenRAWTCPSocket(void);
int PacketReadTCP(int socket, struct iphdr* ipPtr, struct tcphdr* tcpPtr);
int VerifyTCPPortUsed(struct sockaddr_in client, struct sockaddr_in server, int port);
int GetHostName(char* resolvedHost, const char* unresolvedHost);
char* ReportPacketType(struct tcphdr tcpPkt);
void RecordInfor(char* attackalertHost, char* attackalertIp, int attackPort, char* attackPacketType);
void getAttackIpAddress(char* attackalertAddress, char* attackalertIp);
void write_login_address(const char* login_ip, const char* login_address);
#endif // !_OAMDEFENSE_H_
#include "oamDefense.h"
/****************************************************************
* function name : SafeStrncpy
* functional description : 字符串拷贝
* input parameter : dest:存放字符串;src:源串;size:字符串长度
* output parameter : None
* return value: 失败返回NULL
* history :
*****************************************************************/
char* SafeStrncpy(char* dest, const char* src, size_t size)
{
if (!dest)
{
dest = NULL;
return (NULL);
}
else if (size < 1)
{
dest = NULL;
return (NULL);
}
memset(dest, '\0', size);
strncpy(dest, src, size - 1);
return (dest);
}
/****************************************************************
* function name : ConfigTokenRetrieve
* functional description : 从配置文件中获取要监听的端口
* input parameter : token:类型名称;configToken:存放监听的端口
* output parameter : None
* return value: 失败返回-1
*****************************************************************/
int ConfigTokenRetrieve(char* token, char* configToken)
{
FILE* config;
char buffer[MIDLEN], tokenBuffer[MIDLEN];
int count = 0;
if ((config = fopen(CONFIG_FILE, "r")) == NULL)
{
Log(LOGFILE, "%d [%s] [error] Cannot open config file: %s\n", __LINE__, __FUNCTION__, CONFIG_FILE);
return (ERROR);
}
else
{
while ((fgets(buffer, MIDLEN, config)) != NULL)
{
if (buffer[0] != '#')
{
if ((strstr(buffer, token) != NULL) &&
((buffer[strlen(token)] == '=') || (buffer[strlen(token)] == ' ')))
{
/* cut off the '=' and send it back */
if (strstr(buffer, "\"") == NULL)
{
Log(LOGFILE, "%d [%s] [error] adminalert: Quotes missing from %s token. Option skipped\n",
__LINE__, __FUNCTION__, token);
fclose(config);
return (FALSE);
}
SafeStrncpy(tokenBuffer, strstr(buffer, "\"") + 1, MIDLEN);
count = 0;
while (count < MIDLEN - 1)
{
if ((isprint(tokenBuffer[count])) && tokenBuffer[count] != '"')
configToken[count] = tokenBuffer[count];
else
{
configToken[count] = '\0';
break;
}
count++;
}
configToken[MIDLEN - 1] = '\0';
fclose(config);
return (TRUE);
}
}
}
fclose(config);
return (FALSE);
}
}
/****************************************************************
* function name : OpenTCPSocket
* functional description : 创建socket套接字
* input parameter : None
* output parameter : None
* return value: 成功返回套接字ID;失败返回-1
* history :
*****************************************************************/
int OpenTCPSocket(void)
{
int sockfd;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return (ERROR);
else
return (sockfd);
}
/****************************************************************
* function name : BindSocket
* functional description : 绑定、监听端口
* input parameter : sockfd:套接字ID;client:结构体;server:结构体;port:端口
* output parameter : None
* return value: 失败返回-1
* history :
*****************************************************************/
int BindSocket(int sockfd, struct sockaddr_in client, struct sockaddr_in server, int port)
{
bzero((char*)& server, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(port);
if (bind(sockfd, (struct sockaddr*) & server, sizeof(server)) < 0)
{
return (ERROR);
}
else
{
listen(sockfd, 5);
return (TRUE);
}
}
/****************************************************************
* function name : OpenRAWTCPSocket
* functional description : 监听原始套接字
* input parameter : None
* output parameter : None
* return value: 成功返回套接字ID;失败返回-1
* history :
*****************************************************************/
int OpenRAWTCPSocket(void)
{
int sockfd;
if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0)
return (ERROR);
else
return (sockfd);
}
/****************************************************************
* function name : PacketReadTCP
* functional description : 读取TCP数据包
* input parameter : socket:套接字;ipPtr:ip数据包结构体;tcpPtr:tcp数据包结构体
* output parameter : None
* return value: 成功返回套接字ID;失败返回-1
* history :
*****************************************************************/
int PacketReadTCP(int socket, struct iphdr* ipPtr, struct tcphdr* tcpPtr)
{
char packetBuffer[TCPPACKETLEN];
struct in_addr addr;
bzero(ipPtr, sizeof(struct iphdr));
bzero(tcpPtr, sizeof(struct tcphdr));
if (read(socket, packetBuffer, TCPPACKETLEN) == ERROR) return(ERROR);
memcpy(ipPtr, (struct iphdr*) packetBuffer, sizeof(struct iphdr));
if ((ipPtr->ihl < 5) || (ipPtr->ihl > 15))
{
addr.s_addr = (u_int)ipPtr->saddr;
Log(LOGFILE, "%d [%s] [info] attackalert: Illegal IP header length detected in TCP packet: %d from (possible) host: %s\n",
__LINE__, __FUNCTION__, ipPtr->ihl, inet_ntoa(addr));
return (FALSE);
}
else
{
memcpy(tcpPtr, (struct tcphdr*) (packetBuffer + ((ipPtr->ihl) * 4)),
sizeof(struct tcphdr));
return (TRUE);
}
}
/****************************************************************
* function name : VerifyTCPPortUsed
* functional description : 检查端口有无被绑定
* input parameter : client:客户端结构体;server:服务端结构体;port:端口
* output parameter : None
* return value: 端口已被绑定返回TRUE;未被绑定返回FALSE
* history :
*****************************************************************/
int VerifyTCPPortUsed(struct sockaddr_in client, struct sockaddr_in server, int port)
{
int testSockfd;
if ((testSockfd = OpenTCPSocket()) == ERROR)
{
Log(LOGFILE, "%d [%s] [error] could not open TCP socket :%d\n", __LINE__, __FUNCTION__,port);
return (FALSE);
}
else
{
if (BindSocket(testSockfd, client, server, port) == ERROR)
{
Log(LOGFILE, "%d [%s] [info] Port In Use: %d\n", __LINE__, __FUNCTION__, port);
close(testSockfd);
return (TRUE);
}
}
close(testSockfd);
return (FALSE);
}
/****************************************************************
* function name : GetHostName
* functional description : 获取主机名
* input parameter : resolvedHost:存放主机名字符串;unresolvedHost:IP地址
* output parameter : None
* return value: 执行成功返回TRUE
* history :
*****************************************************************/
int GetHostName(char* resolvedHost, const char* unresolvedHost)
{
struct hostent* hostPtr = NULL;
struct in_addr addr;
memset(resolvedHost, '\0', DNSMAXBUF);
if (unresolvedHost == NULL) return(ERROR);
if ((inet_aton(unresolvedHost, &addr)) == 0) return(ERROR);
hostPtr = gethostbyaddr((char*)& addr.s_addr, sizeof(addr.s_addr), AF_INET);
if (hostPtr != NULL)
snprintf(resolvedHost, DNSMAXBUF, "%s", hostPtr->h_name);
else
snprintf(resolvedHost, DNSMAXBUF, "%s", unresolvedHost);
return (TRUE);
}
/****************************************************************
* function name : ReportPacketType
* functional description : 获取扫描类型
* input parameter : tcpPkt:tcp数据包结构体
* output parameter : None
* return value: 返回扫描类型字符串
* history :
*****************************************************************/
char* ReportPacketType(struct tcphdr tcpPkt)
{
static char packetDesc[MAXLEN];
static char* packetDescPtr = packetDesc;
if ((tcpPkt.syn == 0) && (tcpPkt.fin == 0) && (tcpPkt.ack == 0) \
&& (tcpPkt.psh == 0) && (tcpPkt.rst == 0) && (tcpPkt.urg == 0))
snprintf(packetDesc, MAXLEN, " TCP NULL scan");
else if ((tcpPkt.fin == 1) && (tcpPkt.urg == 1) && (tcpPkt.psh == 1))
snprintf(packetDesc, MAXLEN, "TCP XMAS scan");
else if ((tcpPkt.fin == 1) && (tcpPkt.syn != 1) && (tcpPkt.ack != 1) \
&& (tcpPkt.psh != 1) && (tcpPkt.rst != 1) && (tcpPkt.urg != 1))
snprintf(packetDesc, MAXLEN, "TCP FIN scan");
else if ((tcpPkt.syn == 1) && (tcpPkt.fin != 1) && (tcpPkt.ack != 1) \
&& (tcpPkt.psh != 1) && (tcpPkt.rst != 1) && (tcpPkt.urg != 1))
snprintf(packetDesc, MAXLEN, "TCP SYN/Normal scan");
else
snprintf(packetDesc, MAXLEN,
"Unknown Type: TCP Packet Flags: SYN: %d FIN: %d ACK: %d PSH: %d URG: %d RST: %d",
tcpPkt.syn, tcpPkt.fin, tcpPkt.ack, tcpPkt.psh, tcpPkt.urg,
tcpPkt.rst);
return (packetDescPtr);
}
/****************************************************************
* function name : getAttackIpAddress
* functional description : 获取IP地址的位置信息
* input parameter :attackalertAddress:地理位置;attackalertIp:攻击者IP
* output parameter : None
* return value: None
* history :
*****************************************************************/
void getAttackIpAddress(char* attackalertAddress, char* attackalertIp)
{
if (strlen(attackalertIp) == 0) return;
char cmd[MIDLEN] = "";
char retVal[MIDLEN] = "";
/*先查询/var/log/login_message文件,匹配到的话就不需要使用curl查询*/
sprintf(cmd, "cat /var/log/login_message | grep %s | awk -F ':' '{print $2}'", attackalertIp);
sprintf(retVal, "%s", cmdSystem(cmd));
remove_line(retVal);
if (strlen(retVal) == 0)
{
memset(cmd, '\0', MIDLEN);
memset(retVal, '\0', MIDLEN);
//sprintf(cmd, "curl --connect-timeout 30 cip.cc?ip=%s | head -n 2 | grep -v IP | awk -F ':' '{print $2}'", attackalertIp);
sprintf(cmd, "curl --connect-timeout 10 http://ip-api.com/json/%s?lang=zh-CN", attackalertIp);
sprintf(retVal, "%s", cmdSystem(cmd));
remove_line(retVal);
cJSON* json = NULL;
json = cJSON_Parse(retVal);
if (json == NULL) return;
cJSON* node = NULL;
node = cJSON_GetObjectItem(json, "city");
if (node == NULL) return;
sprintf(retVal, "%s", node->valuestring);
/*地址信息写入文件*/
write_login_address(attackalertIp, retVal);
}
sprintf(attackalertAddress, "%s", retVal);
}
/****************************************************************
* function name : write_login_address
* functional description : 登录信息写入文件
* input parameter : login_ip:登录IP;login_address:来源IP地址
* return value: None
*****************************************************************/
void write_login_address(const char* login_ip, const char* login_address)
{
FILE* fp = fopen("/var/log/login_message", "a+");
if (fp == NULL) return;
fprintf(fp, "%s:%s\n", login_ip, login_address);
fclose(fp);
}
/****************************************************************
* function name : RecordInfor
* functional description : 输出结果
* input parameter : attackalertHost:攻击主机名;attackalertIp:攻击的IP;attackPort:攻击的端口;attackPacketType:攻击类型
* output parameter : None
* return value: None
* history :
*****************************************************************/
void RecordInfor(char* attackalertHost, char* attackalertIp, int attackPort, char* attackPacketType)
{
char attackTime[MIDLEN] = "";
sprintf(attackTime, cmdSystem("date \"+\%Y-\%m-\%d \%H:\%M:\%S\""));
remove_line(attackTime);
char attackalertAddress[MIDLEN] = "";
getAttackIpAddress(attackalertAddress, attackalertIp);
FILE* fp = NULL;
if (!(fp = fopen(GLOBAL_ATTACK_LOG_FILE_PATH, "a+")))
return;
fprintf(fp, "{\"attackTime\":\"%s\",\"attackType\":\"portScan\",\"attackalertHost\":\"%s\","
"\"attackalertIp\":\"%s\",\"attackalertAddress\":\"%s\",\"attackTarget\":\"%d\",\"attackPacketType\":\"%s\"}\n",
attackTime,
attackalertHost,
attackalertIp,
attackalertAddress,
attackPort,
attackPacketType);
fclose(fp);
fp = NULL;
Log(LOGFILE, "%d [%s] [info] [attackalert]**********************************************************\n",
__LINE__, __FUNCTION__);
Log(LOGFILE, "%d [%s] [info] [attackalert][Host Name] %s\n",
__LINE__, __FUNCTION__, attackalertHost);
Log(LOGFILE, "%d [%s] [info] [attackalert][IP Address] %s\n",
__LINE__, __FUNCTION__, attackalertIp);
Log(LOGFILE, "%d [%s] [info] [attackalert][Actual Address] %s\n",
__LINE__, __FUNCTION__, attackalertAddress);
Log(LOGFILE, "%d [%s] [info] [attackalert][PORT] %d\n",
__LINE__, __FUNCTION__, attackPort);
Log(LOGFILE, "%d [%s] [info] [attackalert][Attack types] %s\n",
__LINE__, __FUNCTION__, attackPacketType);
Log(LOGFILE, "%d [%s] [info] [attackalert]**********************************************************\n",
__LINE__, __FUNCTION__);
/*添加攻击IP黑名单*/
char cmd[MIDLEN] = "";
char retVal[MIDLEN] = "";
sprintf(cmd, "iptables -S INPUT | grep %s", attackalertIp);
sprintf(retVal, cmdSystem(cmd));
remove_line(retVal);
if (strlen(retVal) == 0)
{
memset(cmd, '\0', MIDLEN);
sprintf(cmd, "iptables -I INPUT -s %s -j DROP", attackalertIp);
system(cmd);
}
return;
}
/****************************************************************
* function name : MonitorStealthModeTCP
* functional description : portSentry端口监控
* input parameter : None
* return value: 失败返回-1
*****************************************************************/
int MonitorStealthModeTCP()
{
struct sockaddr_in client, server;
int portCount = 0, portCount2 = 0, ports[MAXSOCKS], portsDeal[MAXSOCKS];
int count = 0, gotBound = FALSE;
int openSockfd = 0, scanPort = 0;
char* temp, target[IPMAXBUF], configToken[MAXLEN];
char resolvedHost[DNSMAXBUF], * packetType;
struct in_addr addr;
struct iphdr ip;
struct tcphdr tcp;
if ((ConfigTokenRetrieve("TCP_PORTS", configToken)) == FALSE)
{
Log(LOGFILE, "%d [%s] [error] Could not read TCP_PORTS option from config file\n", __LINE__, __FUNCTION__);
return (ERROR);
}
/*解析端口*/
if ((temp = (char*)strtok(configToken, ",")) != NULL)
{
ports[0] = atoi(temp);
for (count = 1; count < MAXSOCKS; count++)
{
if ((temp = (char*)strtok(NULL, ",")) != NULL)
ports[count] = atoi(temp);
else
break;
}
portCount = count;
}
else
{
Log(LOGFILE, "%d [%s] [error] No TCP ports supplied in config file. Aborting\n", __LINE__, __FUNCTION__);
return (ERROR);
}
for (count = 0; count < portCount; count++)
{
Log(LOGFILE, "%d [%s] [info] adminalert: Going into stealth listen mode on TCP port: %d\n",
__LINE__, __FUNCTION__, ports[count]);
if ((openSockfd = OpenTCPSocket()) == ERROR)
{
Log(LOGFILE, "%d [%s] [error] adminalert: ERROR: could not open TCP socket. Aborting.\n", __LINE__, __FUNCTION__);
return (ERROR);
}
if (BindSocket(openSockfd, client, server, ports[count]) == ERROR)
{
Log(LOGFILE, "%d [%s] [error]Socket %d is in use and will not be monitored. Attempting to continue\n",
__LINE__, __FUNCTION__, ports[count]);
}
else
{
gotBound = TRUE;
portsDeal[portCount2++] = ports[count];
}
close(openSockfd);
}
/*没有绑定任何端口*/
if (gotBound == FALSE)
{
Log(LOGFILE, "%d [%s] [error]All supplied TCP sockets are in use and will not be listened to. Shutting down.\n",
__LINE__, __FUNCTION__);
return (ERROR);
}
/*监听原始套接字,解析数据包*/
if ((openSockfd = OpenRAWTCPSocket()) == ERROR)
{
Log(LOGFILE, "%d [%s] [error] could not open RAW TCP socket. Aborting.\n",
__LINE__, __FUNCTION__);
return (ERROR);
}
for (;;)
{
if (PacketReadTCP(openSockfd, &ip, &tcp) != TRUE) continue;
//目的端口号
scanPort = ntohs(tcp.dest);
//没有建立连接,没有设置阻断
if ((tcp.ack != 1) && (tcp.rst != 1))
{
for (count = 0; count < portCount; count++)
{
if (scanPort == portsDeal[count])
{
//端口绑定失败,break
if (VerifyTCPPortUsed(client, server, scanPort) == TRUE) break;
//源地址
addr.s_addr = (u_int)ip.saddr;
//对设备进行扫描的IP
SafeStrncpy(target, (char*)inet_ntoa(addr), IPMAXBUF);
if (GetHostName(resolvedHost, target) != TRUE)
{
/*没有获取到主机名*/
snprintf(resolvedHost, DNSMAXBUF, "%s", target);
}
packetType = ReportPacketType(tcp);
RecordInfor(resolvedHost, target, portsDeal[count], packetType);
break;
}
}
}
}
}
/****************************************************************
* function name : OpenUDPSocket
* functional description : 创建UDP socket
* input parameter : None
* return value: 失败返回-1
*****************************************************************/
int OpenUDPSocket(void)
{
int sockfd;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return (ERROR);
else
return (sockfd);
}
/****************************************************************
* function name : OpenRAWUDPSocket
* functional description : 创建UDP 原始套接字
* input parameter : None
* return value: 失败返回-1
*****************************************************************/
int OpenRAWUDPSocket(void)
{
int sockfd;
if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) < 0)
return (ERROR);
else
return (sockfd);
}
/****************************************************************
* function name : PacketReadUDP
* functional description : 读取UDP数据包
* input parameter : None
* return value: 失败返回-1
*****************************************************************/
int PacketReadUDP(int socket, struct iphdr* ipPtr, struct udphdr* udpPtr)
{
char packetBuffer[UDPPACKETLEN];
struct in_addr addr;
bzero(ipPtr, sizeof(struct iphdr));
bzero(udpPtr, sizeof(struct udphdr));
if (read(socket, packetBuffer, UDPPACKETLEN) == ERROR)
return(ERROR);
memcpy(ipPtr, (struct iphdr*)packetBuffer, sizeof(struct iphdr));
if ((ipPtr->ihl < 5) || (ipPtr->ihl > 15))
{
addr.s_addr = (u_int)ipPtr->saddr;
Log(LOGFILE, "attackalert: Illegal IP header length detected in UDP packet: %d from (possible) host: %s\n",
ipPtr->ihl, inet_ntoa(addr));
return (FALSE);
}
else
{
memcpy(udpPtr, (struct udphdr*)(packetBuffer + ((ipPtr->ihl) * 4)),
sizeof(struct udphdr));
return (TRUE);
}
}
/****************************************************************
* function name : SmartVerifyUDP
* functional description : 验证端口被扫描
* input parameter : None
* return value: 失败返回-1
*****************************************************************/
int SmartVerifyUDP(struct sockaddr_in client, struct sockaddr_in server, int port)
{
int testSockfd;
if ((testSockfd = OpenUDPSocket()) == ERROR)
{
Log(LOGFILE, "adminalert: ERROR: could not open UDP socket to smart-verify.\n");
return (FALSE);
}
else
{
if (BindSocket(testSockfd, client, server, port) == ERROR)
{
close(testSockfd);
return (TRUE);
}
}
close(testSockfd);
return (FALSE);
}
/****************************************************************
* function name : MonitorStealthModeUDP
* functional description : portSentry UDP端口监控
* input parameter : None
* return value: 失败返回-1
*****************************************************************/
int MonitorStealthModeUDP()
{
struct sockaddr_in client, server;
int portCount = 0, portCount2 = 0, ports[MAXSOCKS], ports2[MAXSOCKS], result = TRUE;
int count = 0, scanDetectTrigger = TRUE, gotBound = FALSE;
int openSockfd = 0, incomingPort = 0;
char* temp, target[IPMAXBUF], configToken[MIDLEN];
char resolvedHost[DNSMAXBUF];
struct in_addr addr;
struct iphdr ip;
struct udphdr udp;
if ((ConfigTokenRetrieve("UDP_PORTS", configToken)) == FALSE)
{
Log(LOGFILE, "%d [%s] [error] Could not read UDP_PORTS option from config file\n", __LINE__, __FUNCTION__);
return (ERROR);
}
/* 解析端口*/
if ((temp = (char*)strtok(configToken, ",")) != NULL)
{
ports[0] = atoi(temp);
for (count = 1; count < MAXSOCKS; count++)
{
if ((temp = (char*)strtok(NULL, ",")) != NULL)
ports[count] = atoi(temp);
else
break;
}
portCount = count;
}
else
{
Log(LOGFILE, "%d [%s] [error] No UDP ports supplied in config file. Aborting\n", __LINE__, __FUNCTION__);
return (ERROR);
}
for (count = 0; count < portCount; count++)
{
Log(LOGFILE, "%d [%s] [info] adminalert: Going into stealth listen mode on UDP port: %d\n",
__LINE__, __FUNCTION__, ports[count]);
if ((openSockfd = OpenUDPSocket()) == ERROR)
{
Log(LOGFILE, "%d [%s] [error] adminalert: ERROR: could not open UDP socket. Aborting.\n",
__LINE__, __FUNCTION__);
return (ERROR);
}
if (BindSocket(openSockfd, client, server, ports[count]) == ERROR)
Log(LOGFILE, "%d [%s] [error]Socket %d is in use and will not be monitored. Attempting to continue\n",
__LINE__, __FUNCTION__, ports[count]);
else
{
gotBound = TRUE;
ports2[portCount2++] = ports[count];
}
close(openSockfd);
}
if (gotBound == FALSE)
{
Log(LOGFILE, "%d [%s] [error]All supplied UDP sockets are in use and will not be listened to. Shutting down.\n",
__LINE__, __FUNCTION__);
return (ERROR);
}
if ((openSockfd = OpenRAWUDPSocket()) == ERROR)
{
Log(LOGFILE, "%d [%s] [error] could not open RAW TCP socket. Aborting.\n",
__LINE__, __FUNCTION__);
return (ERROR);
}
for (;;)
{
if (PacketReadUDP(openSockfd, &ip, &udp) != TRUE)
continue;
incomingPort = ntohs(udp.dest);
/* this iterates the list of ports looking for a match */
for (count = 0; count < portCount; count++)
{
if (incomingPort == ports2[count])
{
if (SmartVerifyUDP(client, server, incomingPort) == TRUE)
break;
/*源地址*/
addr.s_addr = (u_int)ip.saddr;
SafeStrncpy(target, (char*)inet_ntoa(addr), IPMAXBUF);
if (GetHostName(resolvedHost, target) != TRUE)
{
/*没有获取到主机名*/
snprintf(resolvedHost, DNSMAXBUF, "%s", target);
}
RecordInfor(resolvedHost, target, ports2[count], "UDP SCAN");
break;
}
}
}
}
/****************************************************************
* function name : thread_portSentryTCP
* functional description : portSentry线程函数
* input parameter : None
* return value: None
*****************************************************************/
void thread_portSentryTCP(void)
{
MonitorStealthModeTCP();
pthread_exit(0);
}
/****************************************************************
* function name : thread_portSentryUDP
* functional description : portSentry线程函数
* input parameter : None
* return value: None
*****************************************************************/
void thread_portSentryUDP(void)
{
MonitorStealthModeUDP();
pthread_exit(0);
}
int main()
{
Log(LOGFILE, "%d [%s] [info] begin\n", __LINE__, __FUNCTION__);
pthread_t portSentry_tcp_id;
if (pthread_create(&portSentry_tcp_id, NULL, (void*)thread_portSentryTCP, NULL) != 0)
{
Log(LOGFILE, LOGFILE, "%d [%s] [error] pthread create error.\n", __LINE__, __FUNCTION__);
}
pthread_t portSentry_udp_id;
if (pthread_create(&portSentry_udp_id, NULL, (void*)thread_portSentryUDP, NULL) != 0)
{
Log(LOGFILE, LOGFILE, "%d [%s] [error] pthread create error.\n", __LINE__, __FUNCTION__);
}
while (1)
{
sleep(10);
}
return 0;
}
上面代码缺少common.h,cJSON.h文件,无法编译。
可以将上面代码中不相关的部分删除,编译后即可正常使用。
最终当检测到其他机器在扫描本机的时候,会显示在日志文件中,iptables中也会添加相应的drop规则。