portSentry入侵检测工具

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规则。

猜你喜欢

转载自blog.csdn.net/xiadeliang1111/article/details/117741592