Compare commits
5 Commits
130dad7ffa
...
4aa0d3eac7
Author | SHA1 | Date | |
---|---|---|---|
4aa0d3eac7 | |||
0b5e40d5c4 | |||
d1ae9fc12c | |||
8d613b3e54 | |||
3aa4d63799 |
11
.vscode/launch.json
vendored
Normal file
11
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
// 使用 IntelliSense 了解相关属性。
|
||||||
|
// 悬停以查看现有属性的描述。
|
||||||
|
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
11
.vscode/settings.json
vendored
11
.vscode/settings.json
vendored
@ -7,6 +7,15 @@
|
|||||||
"clamscan.h": "c",
|
"clamscan.h": "c",
|
||||||
"libiptc.h": "c",
|
"libiptc.h": "c",
|
||||||
"stdio.h": "c",
|
"stdio.h": "c",
|
||||||
"nginx.h": "c"
|
"nginx.h": "c",
|
||||||
|
"cjson.h": "c",
|
||||||
|
"stdlib.h": "c",
|
||||||
|
"stddef.h": "c",
|
||||||
|
"signal.h": "c",
|
||||||
|
"time.h": "c",
|
||||||
|
"stdarg.h": "c",
|
||||||
|
"libclamav.h": "c",
|
||||||
|
"rhost.h": "c",
|
||||||
|
"warning.h": "c"
|
||||||
}
|
}
|
||||||
}
|
}
|
8
Makefile
8
Makefile
@ -20,9 +20,6 @@ ARCH := $(shell bash get_architecture.sh)
|
|||||||
IPTC_CFLAGS += -DHAVE_CONFIG_H -I./libiptc -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 -D_REENTRANT
|
IPTC_CFLAGS += -DHAVE_CONFIG_H -I./libiptc -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 -D_REENTRANT
|
||||||
IPTC_LIB += -lip4tc
|
IPTC_LIB += -lip4tc
|
||||||
|
|
||||||
cJSON_CFLAGS += -std=c89 -c -fPIC -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion -fstack-protector
|
|
||||||
cJSON_LIB += cJSON.o
|
|
||||||
|
|
||||||
ip2region_CFLAGS += -Os -g -Wall -I/ip2region -c
|
ip2region_CFLAGS += -Os -g -Wall -I/ip2region -c
|
||||||
ip2region_LIB += ip2region.o xdb_searcher.o
|
ip2region_LIB += ip2region.o xdb_searcher.o
|
||||||
|
|
||||||
@ -38,10 +35,9 @@ LIBCOMMON_LIB += ./clamav/common/cert_util.c.o ./clamav/common/actions.c.o ./cla
|
|||||||
|
|
||||||
all: libclamav_rust libclamav rhost nginx.o
|
all: libclamav_rust libclamav rhost nginx.o
|
||||||
|
|
||||||
rhost: conf.o rhost.o libiptc.o ccronexpr.o nginx.o disk.o
|
rhost: conf.o common.o rhost.o libiptc.o ccronexpr.o rule.o nginx.o disk.o ip.o warning.o
|
||||||
$(CC) $(ip2region_CFLAGS) ip2region/ip2region.c
|
$(CC) $(ip2region_CFLAGS) ip2region/ip2region.c
|
||||||
$(CC) $(ip2region_CFLAGS) ip2region/xdb_searcher.c
|
$(CC) $(ip2region_CFLAGS) ip2region/xdb_searcher.c
|
||||||
$(CC) $(cJSON_CFLAGS) cJSON/cJSON.c
|
|
||||||
|
|
||||||
$(CC) $(CLAMAV_CFLAGS) -o ./clamav/clamscan/clamscan.c.o -c ./clamav/clamscan/clamscan.c
|
$(CC) $(CLAMAV_CFLAGS) -o ./clamav/clamscan/clamscan.c.o -c ./clamav/clamscan/clamscan.c
|
||||||
$(CC) $(CLAMAV_CFLAGS) -o ./clamav/clamscan/manager.c.o -c ./clamav/clamscan/manager.c
|
$(CC) $(CLAMAV_CFLAGS) -o ./clamav/clamscan/manager.c.o -c ./clamav/clamscan/manager.c
|
||||||
@ -50,7 +46,7 @@ rhost: conf.o rhost.o libiptc.o ccronexpr.o nginx.o disk.o
|
|||||||
$(CC) $(FRESHCLAM_CFLAGS) -o ./clamav/freshclam/execute.c.o -c ./clamav/freshclam/execute.c
|
$(CC) $(FRESHCLAM_CFLAGS) -o ./clamav/freshclam/execute.c.o -c ./clamav/freshclam/execute.c
|
||||||
$(CC) $(FRESHCLAM_CFLAGS) -o ./clamav/freshclam/notify.c.o -c ./clamav/freshclam/notify.c
|
$(CC) $(FRESHCLAM_CFLAGS) -o ./clamav/freshclam/notify.c.o -c ./clamav/freshclam/notify.c
|
||||||
|
|
||||||
$(CC) $(CFLAGS) $^ -o $(OBG) $(cJSON_LIB) $(ip2region_LIB) $(CLAMAV_LIB) $(IPTC_LIB) $(FRESHCLAM_LIB)
|
$(CC) $(CFLAGS) $^ -o $(OBG) $(ip2region_LIB) $(CLAMAV_LIB) $(IPTC_LIB) $(FRESHCLAM_LIB)
|
||||||
|
|
||||||
chmod +x $(OBG)
|
chmod +x $(OBG)
|
||||||
|
|
||||||
|
30
README.md
30
README.md
@ -84,8 +84,6 @@ Options:
|
|||||||
|
|
||||||
|
|
||||||
May 22 2024 15:05:59 Compile、link.
|
May 22 2024 15:05:59 Compile、link.
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```text
|
```text
|
||||||
@ -93,54 +91,40 @@ May 22 2024 15:05:59 Compile、link.
|
|||||||
global {
|
global {
|
||||||
|
|
||||||
DAEMON = "off"; // on开启后台运行,off不开启(弃用)
|
DAEMON = "off"; // on开启后台运行,off不开启(弃用)
|
||||||
TIME = "10"; // 睡眠时间(大于等于1,单位秒)
|
TIME = "1"; // 睡眠时间(大于等于1,单位秒)
|
||||||
|
|
||||||
|
|
||||||
PUBLIC_IP = "http://inet-ip.info"; // 获取公网IP
|
PUBLIC_IP = "http://inet-ip.info"; // 获取公网IP
|
||||||
|
|
||||||
|
|
||||||
IS_DISK = 1; // 磁盘使用率(1开启,非1关闭)
|
IS_DISK = 1; // 磁盘使用率(1开启,非1关闭)
|
||||||
DISK_USE = 95; // 任意某块磁盘使用率告警(大于等于1)
|
DISK_USE = 50; // 任意某块磁盘使用率告警(大于等于1)
|
||||||
|
|
||||||
|
|
||||||
IS_BLOCKED = 1; // 是否封禁攻击IP(1开启,非1关闭)
|
IS_BLOCKED = 1; // 是否封禁攻击IP(1开启,非1关闭)
|
||||||
REFUSE_NUMBER = 3; // 拒绝攻击次数
|
|
||||||
|
|
||||||
|
IS_MAIL = 0; // 开启邮件告警(1开启,非1关闭)
|
||||||
|
|
||||||
CLAMAV = 1; // clamav 是否扫描病毒(1开启,非1关闭)
|
CLAMAV = 1; // clamav 是否扫描病毒(1开启,非1关闭)
|
||||||
CLAMAV_ARG = "-r / --exclude-dir=^/sys|^/dev|^/proc|^/opt/infected|^/root|^/home|^/mnt|^/usr|^/var --move=/opt/infected --max-filesize 1024M -l clamscan.log";
|
CLAMAV_ARG = "-r / --exclude-dir=^/sys|^/dev|^/proc|^/opt/infected|^/root|^/home|^/mnt|^/usr|^/var --move=/opt/infected --max-filesize 1024M -l clamscan.log";
|
||||||
CLAMAV_TIME = "* 45 11 * * *"; // clamav 扫描时间(Cron格式, 秒 分 时 天 月 周)
|
CLAMAV_TIME = "* 45 11 * * *"; // clamav 扫描时间(Cron格式, 秒 分 时 天 月 周)
|
||||||
|
|
||||||
|
|
||||||
IPV4_RESTRICTION = 1; // 是否启用IP白名单(1开启,非1关闭)
|
IPV4_RESTRICTION = 1; // 是否启用IP白名单(1开启,非1关闭)
|
||||||
IPV4_WHITE_LIST = "1.1.1.1 2.2.2.2 "; // IP白名单(空格隔开)
|
IPV4_WHITE_LIST = "1.1.1.1 2.2.2.2 "; // IP白名单(空格隔开)
|
||||||
|
|
||||||
|
|
||||||
REGION = 1; // 是否启用地域白名单(1开启,非1关闭)
|
REGION = 1; // 是否启用地域白名单(1开启,非1关闭)
|
||||||
IP2REGION = 1; // 是否使用本地 ip2region 地址定位库(1使用,非1不使用)
|
IP2REGION = 1; // 是否使用本地 ip2region 地址定位库(1使用,非1不使用)
|
||||||
REGION_LIST = "河南 郑州 上海"; // 地域列表(空格隔开)
|
REGION_LIST = "河南 郑州 上海"; // 地域列表(空格隔开)
|
||||||
|
|
||||||
|
|
||||||
NGINX = 1; // 是否启用Nginx白名单
|
NGINX = 1; // 是否启用Nginx白名单
|
||||||
NGINX_LOG_FILE= "/usr/local/nginx/logs/access.log"; // Nginx 日志文件
|
#NGINX_LOG_FILE= "/var/log/nginx/access.log"; // Nginx 日志文件
|
||||||
NGINX_REGION_LIST = "中国 河南 郑州 上海"; // 地域列表(空格隔开)
|
NGINX_LOG_FILE= "/opt/nginx/logs/access.log"; // Nginx 日志文件
|
||||||
|
NGINX_REGION_LIST = "中国 河南 郑州 上海 内网"; // 地域列表(空格隔开)
|
||||||
|
|
||||||
IS_MAIL = 0; // 开启邮件告警(1开启,非1关闭)
|
|
||||||
|
|
||||||
|
|
||||||
IS_DING_WEBHOOK = 1; // 开启叮叮告警(1开启,非1关闭)
|
IS_DING_WEBHOOK = 1; // 开启叮叮告警(1开启,非1关闭)
|
||||||
PHONE = "15565979082"; // @的人手机号
|
PHONE = "15565979082"; // @的人手机号
|
||||||
DING_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=396bce0384cded025087cff3c176ea5e9afb9bd8fcaa46d6fa8c51dd172ba513"; // 钉钉WEBHOOK
|
DING_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=396bce0384cded025087cff3c176ea5e9afb9bd8fcaa46d6fa8c51dd172ba513"; // 钉钉WEBHOOK
|
||||||
|
|
||||||
|
|
||||||
IS_QQMAIL = 1; // 开启QQ邮箱告警(默认使用gomail: https://git.aixiao.me/aixiao/gomail.git)(1开启,非1关闭)
|
IS_QQMAIL = 1; // 开启QQ邮箱告警(默认使用gomail: https://git.aixiao.me/aixiao/gomail.git)(1开启,非1关闭)
|
||||||
RECV_MAIL = "1605227279@qq.com"; // 接收者邮箱
|
RECV_MAIL = "1605227279@qq.com"; // 接收者邮箱
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
3110
cJSON/cJSON.c
3110
cJSON/cJSON.c
File diff suppressed because it is too large
Load Diff
293
cJSON/cJSON.h
293
cJSON/cJSON.h
@ -1,293 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef cJSON__h
|
|
||||||
#define cJSON__h
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
|
|
||||||
#define __WINDOWS__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
|
||||||
|
|
||||||
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
|
|
||||||
|
|
||||||
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
|
|
||||||
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
|
|
||||||
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
|
|
||||||
|
|
||||||
For *nix builds that support visibility attribute, you can define similar behavior by
|
|
||||||
|
|
||||||
setting default visibility to hidden by adding
|
|
||||||
-fvisibility=hidden (for gcc)
|
|
||||||
or
|
|
||||||
-xldscope=hidden (for sun cc)
|
|
||||||
to CFLAGS
|
|
||||||
|
|
||||||
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define CJSON_CDECL __cdecl
|
|
||||||
#define CJSON_STDCALL __stdcall
|
|
||||||
|
|
||||||
/* export symbols by default, this is necessary for copy pasting the C and header file */
|
|
||||||
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
|
|
||||||
#define CJSON_EXPORT_SYMBOLS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(CJSON_HIDE_SYMBOLS)
|
|
||||||
#define CJSON_PUBLIC(type) type CJSON_STDCALL
|
|
||||||
#elif defined(CJSON_EXPORT_SYMBOLS)
|
|
||||||
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
|
|
||||||
#elif defined(CJSON_IMPORT_SYMBOLS)
|
|
||||||
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
|
|
||||||
#endif
|
|
||||||
#else /* !__WINDOWS__ */
|
|
||||||
#define CJSON_CDECL
|
|
||||||
#define CJSON_STDCALL
|
|
||||||
|
|
||||||
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
|
|
||||||
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
|
|
||||||
#else
|
|
||||||
#define CJSON_PUBLIC(type) type
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* project version */
|
|
||||||
#define CJSON_VERSION_MAJOR 1
|
|
||||||
#define CJSON_VERSION_MINOR 7
|
|
||||||
#define CJSON_VERSION_PATCH 15
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
/* cJSON Types: */
|
|
||||||
#define cJSON_Invalid (0)
|
|
||||||
#define cJSON_False (1 << 0)
|
|
||||||
#define cJSON_True (1 << 1)
|
|
||||||
#define cJSON_NULL (1 << 2)
|
|
||||||
#define cJSON_Number (1 << 3)
|
|
||||||
#define cJSON_String (1 << 4)
|
|
||||||
#define cJSON_Array (1 << 5)
|
|
||||||
#define cJSON_Object (1 << 6)
|
|
||||||
#define cJSON_Raw (1 << 7) /* raw json */
|
|
||||||
|
|
||||||
#define cJSON_IsReference 256
|
|
||||||
#define cJSON_StringIsConst 512
|
|
||||||
|
|
||||||
/* The cJSON structure: */
|
|
||||||
typedef struct cJSON
|
|
||||||
{
|
|
||||||
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
|
|
||||||
struct cJSON *next;
|
|
||||||
struct cJSON *prev;
|
|
||||||
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
|
|
||||||
struct cJSON *child;
|
|
||||||
|
|
||||||
/* The type of the item, as above. */
|
|
||||||
int type;
|
|
||||||
|
|
||||||
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
|
|
||||||
char *valuestring;
|
|
||||||
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
|
|
||||||
int valueint;
|
|
||||||
/* The item's number, if type==cJSON_Number */
|
|
||||||
double valuedouble;
|
|
||||||
|
|
||||||
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
|
|
||||||
char *string;
|
|
||||||
} cJSON;
|
|
||||||
|
|
||||||
typedef struct cJSON_Hooks
|
|
||||||
{
|
|
||||||
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
|
|
||||||
void *(CJSON_CDECL *malloc_fn)(size_t sz);
|
|
||||||
void (CJSON_CDECL *free_fn)(void *ptr);
|
|
||||||
} cJSON_Hooks;
|
|
||||||
|
|
||||||
typedef int cJSON_bool;
|
|
||||||
|
|
||||||
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
|
|
||||||
* This is to prevent stack overflows. */
|
|
||||||
#ifndef CJSON_NESTING_LIMIT
|
|
||||||
#define CJSON_NESTING_LIMIT 1000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* returns the version of cJSON as a string */
|
|
||||||
CJSON_PUBLIC(const char*) cJSON_Version(void);
|
|
||||||
|
|
||||||
/* Supply malloc, realloc and free functions to cJSON */
|
|
||||||
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
|
|
||||||
|
|
||||||
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
|
|
||||||
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
|
|
||||||
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
|
|
||||||
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
|
|
||||||
|
|
||||||
/* Render a cJSON entity to text for transfer/storage. */
|
|
||||||
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
|
|
||||||
/* Render a cJSON entity to text for transfer/storage without any formatting. */
|
|
||||||
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
|
|
||||||
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
|
|
||||||
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
|
|
||||||
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
|
|
||||||
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
|
|
||||||
/* Delete a cJSON entity and all subentities. */
|
|
||||||
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
|
|
||||||
|
|
||||||
/* Returns the number of items in an array (or object). */
|
|
||||||
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
|
|
||||||
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
|
|
||||||
/* Get item "string" from object. Case insensitive. */
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
|
|
||||||
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
|
|
||||||
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
|
|
||||||
|
|
||||||
/* Check item type and return its value */
|
|
||||||
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
|
|
||||||
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
|
|
||||||
|
|
||||||
/* These functions check the type of an item */
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
|
|
||||||
|
|
||||||
/* These calls create a cJSON item of the appropriate type. */
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
|
|
||||||
/* raw json */
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
|
|
||||||
|
|
||||||
/* Create a string where valuestring references a string so
|
|
||||||
* it will not be freed by cJSON_Delete */
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
|
|
||||||
/* Create an object/array that only references it's elements so
|
|
||||||
* they will not be freed by cJSON_Delete */
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
|
|
||||||
|
|
||||||
/* These utilities create an Array of count items.
|
|
||||||
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
|
|
||||||
|
|
||||||
/* Append item to the specified array/object. */
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
|
|
||||||
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
|
|
||||||
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
|
|
||||||
* writing to `item->string` */
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
|
|
||||||
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
|
|
||||||
|
|
||||||
/* Remove/Detach items from Arrays/Objects. */
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
|
|
||||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
|
|
||||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
|
|
||||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
|
|
||||||
|
|
||||||
/* Update array items. */
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
|
|
||||||
|
|
||||||
/* Duplicate a cJSON item */
|
|
||||||
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
|
|
||||||
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
|
|
||||||
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
|
|
||||||
* The item->next and ->prev pointers are always zero on return from Duplicate. */
|
|
||||||
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
|
|
||||||
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
|
|
||||||
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
|
|
||||||
|
|
||||||
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
|
|
||||||
* The input pointer json cannot point to a read-only address area, such as a string constant,
|
|
||||||
* but should point to a readable and writable address area. */
|
|
||||||
CJSON_PUBLIC(void) cJSON_Minify(char *json);
|
|
||||||
|
|
||||||
/* Helper functions for creating and adding items to an object at the same time.
|
|
||||||
* They return the added item or NULL on failure. */
|
|
||||||
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
|
|
||||||
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
|
|
||||||
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
|
|
||||||
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
|
|
||||||
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
|
|
||||||
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
|
|
||||||
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
|
|
||||||
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
|
|
||||||
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
|
|
||||||
|
|
||||||
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
|
||||||
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
|
|
||||||
/* helper for the cJSON_SetNumberValue macro */
|
|
||||||
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
|
|
||||||
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
|
|
||||||
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
|
|
||||||
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
|
|
||||||
|
|
||||||
/* Macro for iterating over an array or object */
|
|
||||||
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
|
|
||||||
|
|
||||||
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
|
|
||||||
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
|
|
||||||
CJSON_PUBLIC(void) cJSON_free(void *object);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
125
common.c
Normal file
125
common.c
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
|
||||||
|
// 计算字符串长度
|
||||||
|
int _strlen(char *str)
|
||||||
|
{
|
||||||
|
char *_p = NULL;
|
||||||
|
|
||||||
|
if (str == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
_p = strchr(str, '\0');
|
||||||
|
|
||||||
|
if (_p == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return _p - str;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自定义 printf 函数
|
||||||
|
void my_printf(const char *format, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
|
||||||
|
// 打印到控制台
|
||||||
|
vprintf(format, args);
|
||||||
|
va_end(args); // 结束对变参列表的处理
|
||||||
|
|
||||||
|
// 重新启动变参列表
|
||||||
|
va_start(args, format);
|
||||||
|
|
||||||
|
// 打开日志文件(追加模式)
|
||||||
|
FILE *log_file = fopen(PRINT_LOG_FILE, "a");
|
||||||
|
if (log_file != NULL) {
|
||||||
|
// 获取当前时间
|
||||||
|
time_t now = time(NULL);
|
||||||
|
struct tm local_time;
|
||||||
|
localtime_r(&now, &local_time);
|
||||||
|
char time_str[20]; // YYYY-MM-DD HH:MM:SS 格式
|
||||||
|
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &local_time);
|
||||||
|
|
||||||
|
// 打印时间戳到日志文件
|
||||||
|
fprintf(log_file, "[%s] ", time_str);
|
||||||
|
|
||||||
|
// 打印内容到日志文件
|
||||||
|
vfprintf(log_file, format, args);
|
||||||
|
|
||||||
|
// 关闭日志文件
|
||||||
|
fclose(log_file);
|
||||||
|
} else {
|
||||||
|
perror("Unable to open log file");
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args); // 结束对变参列表的处理
|
||||||
|
}
|
||||||
|
|
||||||
|
void split_string(char string[], char delims[], char (*whitelist_ip)[WHITELIST_IP_NUM])
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
char *result = NULL;
|
||||||
|
|
||||||
|
result = strtok(string, delims);
|
||||||
|
while (result != NULL)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
strcpy(whitelist_ip[i], result);
|
||||||
|
result = strtok(NULL, delims);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IP段白名单对比
|
||||||
|
int whitelist(char *client_ip, char (*whitelist_ip)[WHITELIST_IP_NUM])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 1; i < WHITELIST_IP_NUM - 1; i++) {
|
||||||
|
if (strcmp(whitelist_ip[i], "\0") == 0) // 如果字符串为空就跳出循环
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((strncmp(client_ip, whitelist_ip[i], _strlen(whitelist_ip[i]))) == 0) // 对比client_ip长度,
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 地域段白名单对比
|
||||||
|
int isregion(char *str, char (*region_list)[WHITELIST_IP_NUM])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
for (i = 1; i < WHITELIST_IP_NUM - 1; i++) {
|
||||||
|
if (strcmp(region_list[i], "\0") == 0) // 如果字符串为空就跳出循环
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//printf("%s %s\n", str, region_list[i]);
|
||||||
|
// 在str中查找region_list[i]
|
||||||
|
p = strstr(str, region_list[i]);
|
||||||
|
if (p != NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *_time()
|
||||||
|
{
|
||||||
|
char temp[BUFFER];
|
||||||
|
char *wday[] = { "0", "1", "2", "3", "4", "5", "6" };
|
||||||
|
time_t t;
|
||||||
|
struct tm *p;
|
||||||
|
time(&t);
|
||||||
|
p = localtime(&t); // 取得当地时间
|
||||||
|
|
||||||
|
memset(temp, 0, BUFFER);
|
||||||
|
snprintf(temp, BUFFER, "[%d/%02d/%02d %s %02d:%02d:%02d] ", (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday, wday[p->tm_wday], p->tm_hour, p->tm_min, p->tm_sec);
|
||||||
|
|
||||||
|
return strdup(temp);
|
||||||
|
}
|
36
common.h
Normal file
36
common.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef COMMON_H
|
||||||
|
#define COMMON_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "conf.h"
|
||||||
|
|
||||||
|
#define PRINT_LOG_FILE "nginx.log"
|
||||||
|
#define BUFFER 1024
|
||||||
|
#define WHITELIST_IP_NUM 1024
|
||||||
|
|
||||||
|
extern int _strlen(char *str);
|
||||||
|
extern void my_printf(const char *format, ...);
|
||||||
|
extern void split_string(char string[], char delims[], char (*whitelist_ip)[WHITELIST_IP_NUM]);
|
||||||
|
extern int whitelist(char *client_ip, char (*whitelist_ip)[WHITELIST_IP_NUM]);
|
||||||
|
extern char *_time();
|
||||||
|
extern int isregion(char *str, char (*region_list)[WHITELIST_IP_NUM]);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
58
conf.c
58
conf.c
@ -14,9 +14,7 @@ int8_t copy_new_mem(char *src, int src_len, char **dest)
|
|||||||
/* 在content中,设置变量(var)的首地址,值(val)的位置首地址和末地址,返回下一行指针 */
|
/* 在content中,设置变量(var)的首地址,值(val)的位置首地址和末地址,返回下一行指针 */
|
||||||
static char *set_var_val_lineEnd(char *content, char **var, char **val_begin, char **val_end)
|
static char *set_var_val_lineEnd(char *content, char **var, char **val_begin, char **val_end)
|
||||||
{
|
{
|
||||||
|
|
||||||
char *p, *pn, *lineEnd;
|
char *p, *pn, *lineEnd;
|
||||||
;
|
|
||||||
int val_len;
|
int val_len;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -98,12 +96,6 @@ static void parse_global_module(char *content, conf * conf)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcasecmp(var, "REFUSE_NUMBER") == 0) {
|
|
||||||
val_begin_len = val_end - val_begin;
|
|
||||||
conf->REFUSE_NUMBER = atoi(val_begin);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcasecmp(var, "IS_MAIL") == 0) {
|
if (strcasecmp(var, "IS_MAIL") == 0) {
|
||||||
val_begin_len = val_end - val_begin;
|
val_begin_len = val_end - val_begin;
|
||||||
conf->IS_MAIL = atoi(val_begin);
|
conf->IS_MAIL = atoi(val_begin);
|
||||||
@ -132,19 +124,7 @@ static void parse_global_module(char *content, conf * conf)
|
|||||||
val_begin_len = val_end - val_begin;
|
val_begin_len = val_end - val_begin;
|
||||||
conf->IS_QQMAIL = atoi(val_begin);
|
conf->IS_QQMAIL = atoi(val_begin);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
if (strcasecmp(var, "SEND_QQ") == 0) {
|
|
||||||
val_begin_len = val_end - val_begin;
|
|
||||||
if (copy_new_mem(val_begin, val_begin_len, &conf->SEND_QQ) != 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcasecmp(var, "QQMAIL_KEY") == 0) {
|
|
||||||
val_begin_len = val_end - val_begin;
|
|
||||||
if (copy_new_mem(val_begin, val_begin_len, &conf->QQMAIL_KEY) != 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if (strcasecmp(var, "RECV_MAIL") == 0) {
|
if (strcasecmp(var, "RECV_MAIL") == 0) {
|
||||||
val_begin_len = val_end - val_begin;
|
val_begin_len = val_end - val_begin;
|
||||||
if (copy_new_mem(val_begin, val_begin_len, &conf->RECV_MAIL) != 0)
|
if (copy_new_mem(val_begin, val_begin_len, &conf->RECV_MAIL) != 0)
|
||||||
@ -178,12 +158,7 @@ static void parse_global_module(char *content, conf * conf)
|
|||||||
val_begin_len = val_end - val_begin;
|
val_begin_len = val_end - val_begin;
|
||||||
conf->IP2REGION = atoi(val_begin);
|
conf->IP2REGION = atoi(val_begin);
|
||||||
}
|
}
|
||||||
if (strcasecmp(var, "REGION_URL") == 0) {
|
|
||||||
val_begin_len = val_end - val_begin;
|
|
||||||
conf->REGION_URL_LEN = val_begin_len;
|
|
||||||
if (copy_new_mem(val_begin, val_begin_len, &conf->REGION_URL) != 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (strcasecmp(var, "REGION_LIST") == 0) {
|
if (strcasecmp(var, "REGION_LIST") == 0) {
|
||||||
val_begin_len = val_end - val_begin;
|
val_begin_len = val_end - val_begin;
|
||||||
|
|
||||||
@ -308,12 +283,6 @@ void free_conf(conf * conf)
|
|||||||
free(conf->PHONE);
|
free(conf->PHONE);
|
||||||
if (conf->DING_WEBHOOK)
|
if (conf->DING_WEBHOOK)
|
||||||
free(conf->DING_WEBHOOK);
|
free(conf->DING_WEBHOOK);
|
||||||
/*
|
|
||||||
if (conf->SEND_QQ)
|
|
||||||
free(conf->SEND_QQ);
|
|
||||||
if (conf->QQMAIL_KEY)
|
|
||||||
free(conf->QQMAIL_KEY);
|
|
||||||
*/
|
|
||||||
if (conf->RECV_MAIL)
|
if (conf->RECV_MAIL)
|
||||||
free(conf->RECV_MAIL);
|
free(conf->RECV_MAIL);
|
||||||
if (conf->PUBLIC_IP)
|
if (conf->PUBLIC_IP)
|
||||||
@ -323,8 +292,6 @@ void free_conf(conf * conf)
|
|||||||
|
|
||||||
if (conf->REGION_LIST)
|
if (conf->REGION_LIST)
|
||||||
free(conf->REGION_LIST);
|
free(conf->REGION_LIST);
|
||||||
if (conf->REGION_URL)
|
|
||||||
free(conf->REGION_URL);
|
|
||||||
|
|
||||||
if (conf->CLAMAV_TIME)
|
if (conf->CLAMAV_TIME)
|
||||||
free(conf->CLAMAV_TIME);
|
free(conf->CLAMAV_TIME);
|
||||||
@ -345,7 +312,7 @@ void ptintf_conf(conf * conf)
|
|||||||
if (conf->DAEMON)
|
if (conf->DAEMON)
|
||||||
printf("DAEMON %s\n", conf->DAEMON);
|
printf("DAEMON %s\n", conf->DAEMON);
|
||||||
printf("TIME %d\n", conf->TIME);
|
printf("TIME %d\n", conf->TIME);
|
||||||
printf("REFUSE_NUMBER %d\n", conf->REFUSE_NUMBER);
|
|
||||||
printf("IS_MAIL %d\n", conf->IS_MAIL);
|
printf("IS_MAIL %d\n", conf->IS_MAIL);
|
||||||
printf("IS_DING_WEBHOOK %d\n", conf->IS_DING_WEBHOOK);
|
printf("IS_DING_WEBHOOK %d\n", conf->IS_DING_WEBHOOK);
|
||||||
if (conf->PHONE)
|
if (conf->PHONE)
|
||||||
@ -353,12 +320,7 @@ void ptintf_conf(conf * conf)
|
|||||||
if (conf->DING_WEBHOOK)
|
if (conf->DING_WEBHOOK)
|
||||||
printf("DING_WEBHOOK %s\n", conf->DING_WEBHOOK);
|
printf("DING_WEBHOOK %s\n", conf->DING_WEBHOOK);
|
||||||
printf("IS_QQMAIL %d\n", conf->IS_QQMAIL);
|
printf("IS_QQMAIL %d\n", conf->IS_QQMAIL);
|
||||||
/*
|
|
||||||
if (conf->SEND_QQ)
|
|
||||||
printf("%s\n", conf->SEND_QQ);
|
|
||||||
if (conf->QQMAIL_KEY)
|
|
||||||
printf("%s\n", conf->QQMAIL_KEY);
|
|
||||||
*/
|
|
||||||
if (conf->RECV_MAIL)
|
if (conf->RECV_MAIL)
|
||||||
printf("RECV_MAIL %s\n", conf->RECV_MAIL);
|
printf("RECV_MAIL %s\n", conf->RECV_MAIL);
|
||||||
if (conf->PUBLIC_IP)
|
if (conf->PUBLIC_IP)
|
||||||
@ -381,17 +343,3 @@ void ptintf_conf(conf * conf)
|
|||||||
if (conf->NGINX_REGION_LIST)
|
if (conf->NGINX_REGION_LIST)
|
||||||
printf("CLAMAV_ARG %s %d\n", conf->NGINX_REGION_LIST, conf->NGINX_REGION_LIST_LEN);
|
printf("CLAMAV_ARG %s %d\n", conf->NGINX_REGION_LIST, conf->NGINX_REGION_LIST_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void split_string(char string[], char delims[], char (*whitelist_ip)[WHITELIST_IP_NUM])
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
char *result = NULL;
|
|
||||||
|
|
||||||
result = strtok(string, delims);
|
|
||||||
while (result != NULL)
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
strcpy(whitelist_ip[i], result);
|
|
||||||
result = strtok(NULL, delims);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
13
conf.h
13
conf.h
@ -7,8 +7,6 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define WHITELIST_IP_NUM 1024
|
|
||||||
|
|
||||||
typedef struct CONF
|
typedef struct CONF
|
||||||
{
|
{
|
||||||
char *DAEMON;
|
char *DAEMON;
|
||||||
@ -26,7 +24,6 @@ typedef struct CONF
|
|||||||
int CLAMAV_ARG_LEN;
|
int CLAMAV_ARG_LEN;
|
||||||
|
|
||||||
int IS_BLOCKED;
|
int IS_BLOCKED;
|
||||||
int REFUSE_NUMBER;
|
|
||||||
|
|
||||||
// 获取公网IP Url地址
|
// 获取公网IP Url地址
|
||||||
char *PUBLIC_IP;
|
char *PUBLIC_IP;
|
||||||
@ -34,8 +31,6 @@ typedef struct CONF
|
|||||||
// 地域白名单
|
// 地域白名单
|
||||||
int REGION;
|
int REGION;
|
||||||
int IP2REGION;
|
int IP2REGION;
|
||||||
char *REGION_URL;
|
|
||||||
int REGION_URL_LEN;
|
|
||||||
char *REGION_LIST;
|
char *REGION_LIST;
|
||||||
int REGION_LIST_LEN;
|
int REGION_LIST_LEN;
|
||||||
|
|
||||||
@ -65,9 +60,9 @@ typedef struct CONF
|
|||||||
char *RECV_MAIL;
|
char *RECV_MAIL;
|
||||||
} conf;
|
} conf;
|
||||||
|
|
||||||
void read_conf(char *filename, conf * configure);
|
extern void read_conf(char *filename, conf * configure);
|
||||||
void free_conf(conf * conf);
|
extern void free_conf(conf * conf);
|
||||||
void ptintf_conf(conf * conf);
|
extern void ptintf_conf(conf * conf);
|
||||||
void split_string(char string[], char delims[], char (*whitelist_ip)[WHITELIST_IP_NUM]);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
93
disk.c
93
disk.c
@ -1,15 +1,11 @@
|
|||||||
#include <stdio.h>
|
#include "disk.h"
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <mntent.h>
|
|
||||||
#include <sys/statvfs.h>
|
|
||||||
|
|
||||||
// 获取指定路径的磁盘使用率
|
// 获取指定路径的磁盘使用率
|
||||||
int get_disk_usage(const char *path, double *usage) {
|
int get_disk_usage(const char *path, double *usage) {
|
||||||
struct statvfs stat;
|
struct statvfs stat;
|
||||||
|
|
||||||
if (statvfs(path, &stat) != 0) {
|
if (statvfs(path, &stat) != 0) {
|
||||||
// 处理错误
|
|
||||||
perror("statvfs failed");
|
perror("statvfs failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -23,37 +19,100 @@ int get_disk_usage(const char *path, double *usage) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int disk_usage() {
|
|
||||||
|
|
||||||
|
// 第三方邮箱告警, 磁盘使用率
|
||||||
|
int QQ_mail_warning_Disk_Use(const char *recv_mail, const char *local_ip, const char *text, int current_length) {
|
||||||
|
|
||||||
|
int command_len = current_length + sizeof(QQMAIL_DISK_USE) + strlen(recv_mail) + strlen(local_ip) + 256;
|
||||||
|
char command[command_len];
|
||||||
|
|
||||||
|
// 生成邮件正文
|
||||||
|
char mail_text[command_len];
|
||||||
|
snprintf(mail_text, command_len, "Host:%s\n%s", local_ip, text);
|
||||||
|
|
||||||
|
// 生成命令字符串
|
||||||
|
snprintf(command, command_len, QQMAIL_DISK_USE, recv_mail, mail_text);
|
||||||
|
|
||||||
|
// 打印命令用于调试
|
||||||
|
printf("Command: %s %d\n", command, current_length);
|
||||||
|
|
||||||
|
// 执行命令
|
||||||
|
int ret = system(command);
|
||||||
|
if (ret == -1) {
|
||||||
|
perror("system command failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int disk_usage(conf *conf, char *local_ip, int threshold) {
|
||||||
FILE *mounts;
|
FILE *mounts;
|
||||||
struct mntent *ent;
|
struct mntent *ent;
|
||||||
|
char *result;
|
||||||
|
size_t result_size = INITIAL_SIZE;
|
||||||
|
size_t current_length = 0;
|
||||||
|
|
||||||
|
result = (char *)malloc(result_size);
|
||||||
|
if (result == NULL) {
|
||||||
|
perror("内存分配失败");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
result[0] = '\0'; // 初始化为空字符串
|
||||||
|
|
||||||
|
// 打开挂载表
|
||||||
mounts = setmntent("/etc/mtab", "r");
|
mounts = setmntent("/etc/mtab", "r");
|
||||||
if (mounts == NULL) {
|
if (mounts == NULL) {
|
||||||
perror("setmntent failed");
|
perror("打开挂载表失败");
|
||||||
|
free(result);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((ent = getmntent(mounts)) != NULL)
|
// 遍历每个挂载的文件系统
|
||||||
{
|
while ((ent = getmntent(mounts)) != NULL) {
|
||||||
double usage = 0;
|
double usage = 0;
|
||||||
if (strstr(ent->mnt_fsname, "/dev/") != NULL)
|
|
||||||
{
|
|
||||||
//printf("%s %s %s\n", ent->mnt_fsname, ent->mnt_dir, ent->mnt_type);
|
|
||||||
|
|
||||||
|
// 检查文件系统是否为设备
|
||||||
|
if (strstr(ent->mnt_fsname, "/dev/") != NULL) {
|
||||||
|
// 获取挂载点的磁盘使用率
|
||||||
if (get_disk_usage(ent->mnt_dir, &usage) != 0) {
|
if (get_disk_usage(ent->mnt_dir, &usage) != 0) {
|
||||||
fprintf(stderr, "Failed to get disk usage for %s\n", ent->mnt_dir);
|
fprintf(stderr, "获取 %s 的磁盘使用率失败\n", ent->mnt_dir);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int threshold = 1;
|
// 如果使用率超过阈值则拼接字符串
|
||||||
if (usage > threshold) {
|
if (usage > threshold) {
|
||||||
printf("挂载点: %s 使用率: %.2f%% 阀值: %d%%\n", ent->mnt_dir, usage, threshold);
|
char buffer[BUFFER_INCREMENT];
|
||||||
|
int len = snprintf(buffer, BUFFER_INCREMENT, "挂载点:%s 使用率:%.2f%% 阀值:%d%%\n", ent->mnt_dir, usage, threshold);
|
||||||
|
|
||||||
|
// 检查缓冲区大小是否足够
|
||||||
|
if (current_length + len >= result_size) {
|
||||||
|
result_size += BUFFER_INCREMENT;
|
||||||
|
result = (char *)realloc(result, result_size);
|
||||||
|
if (result == NULL) {
|
||||||
|
perror("内存重新分配失败");
|
||||||
|
endmntent(mounts);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strcat(result, buffer);
|
||||||
|
current_length += len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 发送邮件警告
|
||||||
|
if (current_length > 0) {
|
||||||
|
if (QQ_mail_warning_Disk_Use(conf->RECV_MAIL, local_ip, result, current_length) != 0) {
|
||||||
|
fprintf(stderr, "发送邮件失败\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理
|
||||||
|
free(result);
|
||||||
endmntent(mounts);
|
endmntent(mounts);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
9
disk.h
9
disk.h
@ -7,6 +7,13 @@
|
|||||||
#include <mntent.h>
|
#include <mntent.h>
|
||||||
#include <sys/statvfs.h>
|
#include <sys/statvfs.h>
|
||||||
|
|
||||||
extern int disk_usage();
|
#include "rhost.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "warning.h"
|
||||||
|
|
||||||
|
#define INITIAL_SIZE 1024
|
||||||
|
#define BUFFER_INCREMENT 512
|
||||||
|
|
||||||
|
int disk_usage(conf *conf, char *local_ip, int threshold);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
98
ip.c
Normal file
98
ip.c
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#include "ip.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct MemoryStruct {
|
||||||
|
char *memory;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||||
|
{
|
||||||
|
size_t realsize = size * nmemb;
|
||||||
|
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
|
||||||
|
|
||||||
|
// 注意这里根据每次被调用获得的数据重新动态分配缓存区的大小
|
||||||
|
char *ptr = realloc(mem->memory, mem->size + realsize + 1);
|
||||||
|
if (ptr == NULL) {
|
||||||
|
/* 内存不足! */
|
||||||
|
printf("not enough memory (realloc returned NULL)\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mem->memory = ptr;
|
||||||
|
memcpy(&(mem->memory[mem->size]), contents, realsize);
|
||||||
|
mem->size += realsize;
|
||||||
|
mem->memory[mem->size] = 0;
|
||||||
|
|
||||||
|
return realsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取公网IP
|
||||||
|
char *GET_PUBLIC_IP(char *URL)
|
||||||
|
{
|
||||||
|
CURL *curl_handle;
|
||||||
|
CURLcode res;
|
||||||
|
|
||||||
|
struct curl_slist *headers = NULL;
|
||||||
|
struct MemoryStruct chunk;
|
||||||
|
|
||||||
|
chunk.memory = malloc(1); /* 将根据上述再分配的需要增长 */
|
||||||
|
chunk.size = 0; /* 此时没有数据 */
|
||||||
|
|
||||||
|
curl_global_init(CURL_GLOBAL_ALL);
|
||||||
|
|
||||||
|
/* 初始化curl会话 */
|
||||||
|
curl_handle = curl_easy_init();
|
||||||
|
|
||||||
|
char *p = NULL;
|
||||||
|
char *buff;
|
||||||
|
|
||||||
|
p = strstr(URL, "-H");
|
||||||
|
if (p) {
|
||||||
|
|
||||||
|
buff = (char *)alloca(p - URL + 1);
|
||||||
|
if (buff == NULL)
|
||||||
|
perror("out of memory.");
|
||||||
|
|
||||||
|
memset(buff, 0, p - URL + 1);
|
||||||
|
memcpy(buff, URL, (int)(p - URL - 1));
|
||||||
|
|
||||||
|
// 赋值header值
|
||||||
|
headers = curl_slist_append(headers, p + 3);
|
||||||
|
|
||||||
|
// 设置header
|
||||||
|
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
|
||||||
|
curl_easy_setopt(curl_handle, CURLOPT_URL, buff);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* 指定要获取的URL */
|
||||||
|
curl_easy_setopt(curl_handle, CURLOPT_URL, URL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 将所有数据发送到此函数 */
|
||||||
|
//对于同一次阻塞的curl_easy_perform而言,在写完获取的数据之前,会多次调用 WriteMemoryCallback
|
||||||
|
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
|
||||||
|
|
||||||
|
/* 将"chunk"结构传递给回调函数 */
|
||||||
|
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
|
||||||
|
|
||||||
|
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
|
||||||
|
|
||||||
|
//对于同一次阻塞的curl_easy_perform而言,在写完获取的数据之前,会多次调用 WriteMemoryCallback
|
||||||
|
res = curl_easy_perform(curl_handle);
|
||||||
|
|
||||||
|
if (res != CURLE_OK) {
|
||||||
|
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||||
|
} else {
|
||||||
|
//printf("%lu bytes retrieved\n", (unsigned long)chunk.size);
|
||||||
|
//printf("%s", chunk.memory);
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_cleanup(curl_handle);
|
||||||
|
curl_global_cleanup();
|
||||||
|
|
||||||
|
return chunk.memory;
|
||||||
|
}
|
22
ip.h
Normal file
22
ip.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef IP_H
|
||||||
|
#define IP_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
extern char *GET_PUBLIC_IP(char *URL);
|
||||||
|
|
||||||
|
#endif
|
7
nginx.c
7
nginx.c
@ -11,7 +11,7 @@ void nginx_iptc(char *ip)
|
|||||||
iptc_add_rule("filter", "INPUT", IPPROTO_TCP, NULL, NULL, srcIp, 0, NULL, NULL, "DROP", NULL, 1);
|
iptc_add_rule("filter", "INPUT", IPPROTO_TCP, NULL, NULL, srcIp, 0, NULL, NULL, "DROP", NULL, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int IP_location(char *string, conf *config)
|
static int Handle_IP(char *string, conf *config)
|
||||||
{
|
{
|
||||||
char *area = NULL;
|
char *area = NULL;
|
||||||
char *xdb_path = "ip2region.xdb";
|
char *xdb_path = "ip2region.xdb";
|
||||||
@ -54,7 +54,8 @@ int IP_location(char *string, conf *config)
|
|||||||
if (config->NGINX == 1) // 开启Nginx防御
|
if (config->NGINX == 1) // 开启Nginx防御
|
||||||
{
|
{
|
||||||
if (isregion(area, nginx_region_list) == 1) { // 返回1表示在白名单列表
|
if (isregion(area, nginx_region_list) == 1) { // 返回1表示在白名单列表
|
||||||
printf(RED "%s Nginx Ip Address: %s, 属于地域白名单: %s\n" COLOR_NONE, t, IP, area);
|
;
|
||||||
|
//printf(RED "%s Nginx Ip Address: %s, 属于地域白名单: %s\n" COLOR_NONE, t, IP, area);
|
||||||
} else {
|
} else {
|
||||||
my_printf(RED "%s Nginx 封禁 Ip Address: %s, 地址: %s!!!\n" COLOR_NONE, t, IP, area);
|
my_printf(RED "%s Nginx 封禁 Ip Address: %s, 地址: %s!!!\n" COLOR_NONE, t, IP, area);
|
||||||
nginx_iptc(IP);
|
nginx_iptc(IP);
|
||||||
@ -136,7 +137,7 @@ int nginx_read_log(const char *filename, conf *p)
|
|||||||
int bytes_read;
|
int bytes_read;
|
||||||
while ((bytes_read = read(fd, read_buf, buffer_size - 1)) > 0) {
|
while ((bytes_read = read(fd, read_buf, buffer_size - 1)) > 0) {
|
||||||
read_buf[bytes_read] = '\0';
|
read_buf[bytes_read] = '\0';
|
||||||
IP_location(read_buf, p);
|
Handle_IP(read_buf, p);
|
||||||
}
|
}
|
||||||
if (bytes_read == -1 && errno != EAGAIN) {
|
if (bytes_read == -1 && errno != EAGAIN) {
|
||||||
perror("read");
|
perror("read");
|
||||||
|
1
nginx.h
1
nginx.h
@ -10,6 +10,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "rhost.h"
|
#include "rhost.h"
|
||||||
|
#include "common.h"
|
||||||
#include "libiptc.h"
|
#include "libiptc.h"
|
||||||
#include "ip2region/ip2region.h"
|
#include "ip2region/ip2region.h"
|
||||||
|
|
||||||
|
789
rhost.c
789
rhost.c
@ -1,11 +1,14 @@
|
|||||||
#include "rhost.h"
|
#include "rhost.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "ip.h"
|
||||||
|
#include "warning.h"
|
||||||
|
#include "rule.h"
|
||||||
#include "libiptc.h"
|
#include "libiptc.h"
|
||||||
#include "libclamav.h"
|
#include "libclamav.h"
|
||||||
#include "clamscan.h"
|
#include "clamscan.h"
|
||||||
#include "ccronexpr.h"
|
#include "ccronexpr.h"
|
||||||
#include "nginx.h"
|
#include "nginx.h"
|
||||||
#include "./cJSON/cJSON.h"
|
#include "disk.h"
|
||||||
#include "ip2region/ip2region.h"
|
#include "ip2region/ip2region.h"
|
||||||
|
|
||||||
// CRON
|
// CRON
|
||||||
@ -47,206 +50,9 @@ void cron_free(void *p)
|
|||||||
// CRON END
|
// CRON END
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 自定义 printf 函数
|
|
||||||
void my_printf(const char *format, ...) {
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
|
|
||||||
// 打印到控制台
|
|
||||||
vprintf(format, args);
|
|
||||||
va_end(args); // 结束对变参列表的处理
|
|
||||||
|
|
||||||
// 重新启动变参列表
|
|
||||||
va_start(args, format);
|
|
||||||
|
|
||||||
// 打开日志文件(追加模式)
|
|
||||||
FILE *log_file = fopen(LOG_FILE, "a");
|
|
||||||
if (log_file != NULL) {
|
|
||||||
// 获取当前时间
|
|
||||||
time_t now = time(NULL);
|
|
||||||
struct tm local_time;
|
|
||||||
localtime_r(&now, &local_time);
|
|
||||||
char time_str[20]; // YYYY-MM-DD HH:MM:SS 格式
|
|
||||||
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &local_time);
|
|
||||||
|
|
||||||
// 打印时间戳到日志文件
|
|
||||||
fprintf(log_file, "[%s] ", time_str);
|
|
||||||
|
|
||||||
// 打印内容到日志文件
|
|
||||||
vfprintf(log_file, format, args);
|
|
||||||
|
|
||||||
// 关闭日志文件
|
|
||||||
fclose(log_file);
|
|
||||||
} else {
|
|
||||||
perror("Unable to open log file");
|
|
||||||
}
|
|
||||||
|
|
||||||
va_end(args); // 结束对变参列表的处理
|
|
||||||
}
|
|
||||||
|
|
||||||
// 存储公网IP
|
// 存储公网IP
|
||||||
char *public_ip;
|
char *public_ip;
|
||||||
|
|
||||||
struct MemoryStruct {
|
|
||||||
char *memory;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 计算字符串长度
|
|
||||||
int _strlen(char *str)
|
|
||||||
{
|
|
||||||
char *_p = NULL;
|
|
||||||
|
|
||||||
if (str == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
_p = strchr(str, '\0');
|
|
||||||
|
|
||||||
if (_p == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return _p - str;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
|
||||||
{
|
|
||||||
size_t realsize = size * nmemb;
|
|
||||||
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
|
|
||||||
|
|
||||||
// 注意这里根据每次被调用获得的数据重新动态分配缓存区的大小
|
|
||||||
char *ptr = realloc(mem->memory, mem->size + realsize + 1);
|
|
||||||
if (ptr == NULL) {
|
|
||||||
/* 内存不足! */
|
|
||||||
printf("not enough memory (realloc returned NULL)\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mem->memory = ptr;
|
|
||||||
memcpy(&(mem->memory[mem->size]), contents, realsize);
|
|
||||||
mem->size += realsize;
|
|
||||||
mem->memory[mem->size] = 0;
|
|
||||||
|
|
||||||
return realsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取公网IP
|
|
||||||
static char *GET_PUBLIC_IP(char *URL)
|
|
||||||
{
|
|
||||||
CURL *curl_handle;
|
|
||||||
CURLcode res;
|
|
||||||
|
|
||||||
struct curl_slist *headers = NULL;
|
|
||||||
struct MemoryStruct chunk;
|
|
||||||
|
|
||||||
chunk.memory = malloc(1); /* 将根据上述再分配的需要增长 */
|
|
||||||
chunk.size = 0; /* 此时没有数据 */
|
|
||||||
|
|
||||||
curl_global_init(CURL_GLOBAL_ALL);
|
|
||||||
|
|
||||||
/* 初始化curl会话 */
|
|
||||||
curl_handle = curl_easy_init();
|
|
||||||
|
|
||||||
char *p = NULL;
|
|
||||||
char *buff;
|
|
||||||
|
|
||||||
p = strstr(URL, "-H");
|
|
||||||
if (p) {
|
|
||||||
|
|
||||||
buff = (char *)alloca(p - URL + 1);
|
|
||||||
if (buff == NULL)
|
|
||||||
perror("out of memory.");
|
|
||||||
|
|
||||||
memset(buff, 0, p - URL + 1);
|
|
||||||
memcpy(buff, URL, (int)(p - URL - 1));
|
|
||||||
|
|
||||||
// 赋值header值
|
|
||||||
headers = curl_slist_append(headers, p + 3);
|
|
||||||
|
|
||||||
// 设置header
|
|
||||||
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
|
|
||||||
curl_easy_setopt(curl_handle, CURLOPT_URL, buff);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* 指定要获取的URL */
|
|
||||||
curl_easy_setopt(curl_handle, CURLOPT_URL, URL);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 将所有数据发送到此函数 */
|
|
||||||
//对于同一次阻塞的curl_easy_perform而言,在写完获取的数据之前,会多次调用 WriteMemoryCallback
|
|
||||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
|
|
||||||
|
|
||||||
/* 将"chunk"结构传递给回调函数 */
|
|
||||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
|
|
||||||
|
|
||||||
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
|
|
||||||
|
|
||||||
//对于同一次阻塞的curl_easy_perform而言,在写完获取的数据之前,会多次调用 WriteMemoryCallback
|
|
||||||
res = curl_easy_perform(curl_handle);
|
|
||||||
|
|
||||||
if (res != CURLE_OK) {
|
|
||||||
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
|
||||||
} else {
|
|
||||||
//printf("%lu bytes retrieved\n", (unsigned long)chunk.size);
|
|
||||||
//printf("%s", chunk.memory);
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_easy_cleanup(curl_handle);
|
|
||||||
curl_global_cleanup();
|
|
||||||
|
|
||||||
return chunk.memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析Json
|
|
||||||
char *process_json(char *buff, char *api)
|
|
||||||
{
|
|
||||||
char *area = NULL;
|
|
||||||
int area_len = 0;
|
|
||||||
char *p = NULL;
|
|
||||||
|
|
||||||
if (buff == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cJSON *cjson_init = cJSON_Parse(buff);
|
|
||||||
if (cjson_init == NULL) {
|
|
||||||
perror("cJSON_Parse");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if ((p = strstr(api, "baidu")) != NULL) { // baidu Api
|
|
||||||
int i;
|
|
||||||
|
|
||||||
cJSON *data = cJSON_GetObjectItem(cjson_init, "data");
|
|
||||||
if (data != NULL) {
|
|
||||||
for (i = 0; i < cJSON_GetArraySize(data); i++) {
|
|
||||||
cJSON *svalue = cJSON_GetArrayItem(data, i);
|
|
||||||
cJSON *location = cJSON_GetObjectItem(svalue, "location");
|
|
||||||
area_len = _strlen(location->valuestring);
|
|
||||||
|
|
||||||
area = (char *)alloca(area_len + 1);
|
|
||||||
if (area == NULL)
|
|
||||||
perror("out of memory.");
|
|
||||||
memset(area, 0, area_len + 1);
|
|
||||||
|
|
||||||
snprintf(area, area_len + 1, "%s", location->valuestring);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cJSON_Delete(cjson_init);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cJSON_Delete(cjson_init);
|
|
||||||
return strdup(area);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检测系统
|
// 检测系统
|
||||||
int check_system()
|
int check_system()
|
||||||
{
|
{
|
||||||
@ -259,504 +65,6 @@ int check_system()
|
|||||||
return UNKNOWN_SYSTEM;
|
return UNKNOWN_SYSTEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 钉钉告警
|
|
||||||
int dingding_warning(char *illegal_ip, char *public_ip, char *ip, conf *conf)
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
char temp[64];
|
|
||||||
char jsonObj[BUFFER];
|
|
||||||
|
|
||||||
memset(jsonObj, 0, BUFFER);
|
|
||||||
memset(temp, 0, 64);
|
|
||||||
strcpy(temp, public_ip);
|
|
||||||
temp[_strlen(public_ip) - 1] = '\0';
|
|
||||||
|
|
||||||
if ((fp = fopen("libcurl.log", "wt+")) == NULL) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
CURL *curl;
|
|
||||||
CURLcode res;
|
|
||||||
|
|
||||||
curl_global_init(CURL_GLOBAL_ALL);
|
|
||||||
curl = curl_easy_init();
|
|
||||||
if (curl == NULL) {
|
|
||||||
fclose(fp);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#define JSIN "{ \
|
|
||||||
\"msgtype\": \"text\", \
|
|
||||||
\"text\": { \
|
|
||||||
\"content\": \"Alert @%s 服务器地址:%s,封禁非法入侵主机:(%s%s)\" \
|
|
||||||
}, \
|
|
||||||
\"at\": { \
|
|
||||||
\"atMobiles\": [\"%s\"], \
|
|
||||||
\"isAtAll\": false \
|
|
||||||
} \
|
|
||||||
}"
|
|
||||||
|
|
||||||
snprintf(jsonObj, BUFFER, JSIN, conf->PHONE, temp, ip, illegal_ip, conf->PHONE);
|
|
||||||
printf("%s\n", jsonObj);
|
|
||||||
|
|
||||||
struct curl_slist *headers = NULL;
|
|
||||||
headers = curl_slist_append(headers, "Accept: application/json");
|
|
||||||
headers = curl_slist_append(headers, "Content-Type: application/json");
|
|
||||||
headers = curl_slist_append(headers, "charset: utf-8");
|
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, conf->DING_WEBHOOK);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonObj);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl/0.1");
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
|
|
||||||
|
|
||||||
res = curl_easy_perform(curl);
|
|
||||||
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
curl_global_cleanup();
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 邮件告警
|
|
||||||
int mail_warning(char *illegal_ip, char *public_ip, char *ip, conf *conf)
|
|
||||||
{
|
|
||||||
FILE *fp = NULL;
|
|
||||||
char buff[BUFFER];
|
|
||||||
char text[BUFFER];
|
|
||||||
char temp[64];
|
|
||||||
|
|
||||||
memset(buff, 0, BUFFER);
|
|
||||||
memset(text, 0, BUFFER);
|
|
||||||
memset(temp, 0, 64);
|
|
||||||
|
|
||||||
strcpy(temp, public_ip);
|
|
||||||
temp[_strlen(public_ip) - 1] = '\0';
|
|
||||||
snprintf(text, BUFFER, "echo \"主机:%s, 禁止(%s%s)访问\" | mail -s \"System ban IP\" %s", temp, ip, illegal_ip, conf->RECV_MAIL);
|
|
||||||
|
|
||||||
if (NULL == (fp = popen(text, "r"))) {
|
|
||||||
perror("popen text");
|
|
||||||
}
|
|
||||||
|
|
||||||
while (fgets(buff, BUFFER, fp) != NULL) {
|
|
||||||
buff[_strlen(buff) - 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL != fp)
|
|
||||||
pclose(fp);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 第三方邮箱告警
|
|
||||||
int QQ_mail_warning(char *illegal_ip, char *public_ip, char *ip, conf *conf)
|
|
||||||
{
|
|
||||||
char string[BUFFER + (sizeof(QQMAIL)) + 1];
|
|
||||||
char text[BUFFER];
|
|
||||||
char temp[32];
|
|
||||||
|
|
||||||
memset(string, 0, BUFFER + (sizeof(QQMAIL)) + 1);
|
|
||||||
memset(text, 0, BUFFER);
|
|
||||||
memset(temp, 0, 32);
|
|
||||||
|
|
||||||
strcpy(temp, public_ip);
|
|
||||||
temp[_strlen(public_ip) - 1] = '\0';
|
|
||||||
|
|
||||||
snprintf(text, BUFFER, "主机:%s, 禁止(%s%s)访问!", temp, ip, illegal_ip);
|
|
||||||
snprintf(string, BUFFER + (sizeof(QQMAIL)) + 1, QQMAIL, conf->RECV_MAIL, text);
|
|
||||||
|
|
||||||
return system(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 第三方邮箱告警, 感染病毒邮件提醒
|
|
||||||
int QQ_mail_warning_Virus_files(char *local_ip, int Virus_number, conf *conf)
|
|
||||||
{
|
|
||||||
char *command;
|
|
||||||
char *text;
|
|
||||||
char temp[32];
|
|
||||||
|
|
||||||
command = (char *)alloca(BUFFER + (sizeof(QQMAIL)) + 1);
|
|
||||||
text = (char *)alloca(BUFFER);
|
|
||||||
|
|
||||||
memset(command, 0, BUFFER + (sizeof(QQMAIL)) + 1);
|
|
||||||
memset(text, 0, BUFFER);
|
|
||||||
memset(temp, 0, 32);
|
|
||||||
|
|
||||||
strcpy(temp, local_ip);
|
|
||||||
temp[_strlen(local_ip) - 1] = '\0';
|
|
||||||
|
|
||||||
snprintf(text, BUFFER, "Host:%s, Infected files: %d, Please handle!", temp, Virus_number);
|
|
||||||
snprintf(command, BUFFER + BUFFER + (sizeof(QQMAIL)) + 1, QQMAIL_Virus, conf->RECV_MAIL, text);
|
|
||||||
|
|
||||||
return system(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 第三方邮箱告警, 磁盘使用率
|
|
||||||
int QQ_mail_warning_Disk_Use(char *local_ip, int disk_use, conf *conf)
|
|
||||||
{
|
|
||||||
char *command;
|
|
||||||
char *text;
|
|
||||||
char temp[32];
|
|
||||||
|
|
||||||
command = (char *)alloca(BUFFER + (sizeof(QQMAIL)) + 1);
|
|
||||||
text = (char *)alloca(BUFFER);
|
|
||||||
|
|
||||||
memset(command, 0, BUFFER + (sizeof(QQMAIL)) + 1);
|
|
||||||
memset(text, 0, BUFFER);
|
|
||||||
memset(temp, 0, 32);
|
|
||||||
|
|
||||||
strcpy(temp, local_ip);
|
|
||||||
temp[_strlen(local_ip) - 1] = '\0';
|
|
||||||
|
|
||||||
snprintf(text, BUFFER, "Host:%s, Disk usage reaches threshold!, Please handle!", temp);
|
|
||||||
snprintf(command, BUFFER, QQMAIL_DISK_USE, conf->RECV_MAIL, text);
|
|
||||||
|
|
||||||
return system(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
// IP段白名单对比
|
|
||||||
int whitelist(char *client_ip, char (*whitelist_ip)[WHITELIST_IP_NUM])
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 1; i < WHITELIST_IP_NUM - 1; i++) {
|
|
||||||
if (strcmp(whitelist_ip[i], "\0") == 0) // 如果字符串为空就跳出循环
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((strncmp(client_ip, whitelist_ip[i], _strlen(whitelist_ip[i]))) == 0) // 对比client_ip长度,
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 地域段白名单对比
|
|
||||||
int isregion(char *str, char (*region_list)[WHITELIST_IP_NUM])
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
for (i = 1; i < WHITELIST_IP_NUM - 1; i++) {
|
|
||||||
if (strcmp(region_list[i], "\0") == 0) // 如果字符串为空就跳出循环
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//printf("%s %s\n", str, region_list[i]);
|
|
||||||
// 在str中查找region_list[i]
|
|
||||||
p = strstr(str, region_list[i]);
|
|
||||||
if (p != NULL) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 磁盘使用率
|
|
||||||
int disk_waring(int threshold)
|
|
||||||
{
|
|
||||||
FILE *fp = NULL;
|
|
||||||
char buffer[BUFFER];
|
|
||||||
char command[BUFFER];
|
|
||||||
int is = 0;
|
|
||||||
|
|
||||||
#define DF "for u in `df -mh | grep -E -e \".:.\" -e \"^/dev\" | awk '{print $5}' | sed 's|%%||g'`; do if test \"$u\" -ge %d; then echo \"$u\"; fi done"
|
|
||||||
|
|
||||||
memset(buffer, 0, BUFFER);
|
|
||||||
memset(command, 0, BUFFER);
|
|
||||||
|
|
||||||
snprintf(command, BUFFER, DF, threshold);
|
|
||||||
|
|
||||||
//printf("%s\n", command);
|
|
||||||
fp = popen(command, "r");
|
|
||||||
|
|
||||||
while (fgets(buffer, BUFFER, fp) != NULL) {
|
|
||||||
printf("%s", buffer);
|
|
||||||
is = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pclose(fp);
|
|
||||||
|
|
||||||
return is;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *_time()
|
|
||||||
{
|
|
||||||
char temp[BUFFER];
|
|
||||||
char *wday[] = { "0", "1", "2", "3", "4", "5", "6" };
|
|
||||||
time_t t;
|
|
||||||
struct tm *p;
|
|
||||||
time(&t);
|
|
||||||
p = localtime(&t); // 取得当地时间
|
|
||||||
|
|
||||||
memset(temp, 0, BUFFER);
|
|
||||||
snprintf(temp, BUFFER, "[%d/%02d/%02d %s %02d:%02d:%02d] ", (1900 + p->tm_year), (1 + p->tm_mon), p->tm_mday, wday[p->tm_wday], p->tm_hour, p->tm_min, p->tm_sec);
|
|
||||||
|
|
||||||
return strdup(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 封禁非法IP
|
|
||||||
int rule(conf *conf)
|
|
||||||
{
|
|
||||||
char whitelist_ip[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } };
|
|
||||||
char region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } };
|
|
||||||
|
|
||||||
char REGION_LIST_COPY[conf->REGION_LIST_LEN + 1];
|
|
||||||
char IPV4_WHITE_LIST_COPY[conf->IPV4_WHITE_LIST_LEN + 1];
|
|
||||||
|
|
||||||
char p_two[2], *command, *splice_command, *temp, buffer[BUFFER], awk[BUFFER];
|
|
||||||
FILE *fp, *fc;
|
|
||||||
time_t timep;
|
|
||||||
struct tm *tp;
|
|
||||||
long int ip_length = 1;
|
|
||||||
|
|
||||||
fp = NULL;
|
|
||||||
fc = NULL;
|
|
||||||
timep = time(NULL);
|
|
||||||
tp = localtime(&timep);
|
|
||||||
memset(buffer, 0, BUFFER);
|
|
||||||
memset(awk, 0, BUFFER);
|
|
||||||
memset(p_two, 0, 2);
|
|
||||||
|
|
||||||
char *t = NULL;
|
|
||||||
t = _time();
|
|
||||||
|
|
||||||
if (DEBISN_SYSTEM == check_system()) // Debian 系统规则
|
|
||||||
{
|
|
||||||
if (system_version() >= 12)
|
|
||||||
{
|
|
||||||
if ((fp = popen(GE_10, "r")) == NULL)
|
|
||||||
{
|
|
||||||
perror("GE_10");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (tp->tm_mday >= 10)
|
|
||||||
{
|
|
||||||
if ((fp = popen(GE_10, "r")) == NULL)
|
|
||||||
{
|
|
||||||
perror("GE_10");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((fp = popen(LE_10, "r")) == NULL)
|
|
||||||
{
|
|
||||||
perror("LE_10");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (CENTOS_SYSTEM == check_system()) // Centos 7系统规则
|
|
||||||
{
|
|
||||||
if (tp->tm_mday >= 10) {
|
|
||||||
if ((fp = popen(CENTOS_GE_10, "r")) == NULL) {
|
|
||||||
perror("CENTOS_GE_10");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((fp = popen(CENTOS_LE_10, "r")) == NULL) {
|
|
||||||
perror("CENTOS_LE_10");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return UNKNOWN_SYSTEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
splice_command = (char *)malloc(ip_length);
|
|
||||||
if (splice_command == NULL) {
|
|
||||||
free(splice_command);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memset(splice_command, 0, ip_length);
|
|
||||||
|
|
||||||
while (fgets(buffer, BUFFER, fp) != NULL) {
|
|
||||||
char *new_splice_command;
|
|
||||||
|
|
||||||
temp = strstr(buffer, "rhost");
|
|
||||||
sscanf(temp, "rhost=%64s", temp);
|
|
||||||
if (atoi(strncpy(p_two, temp, 1)) > 0) {
|
|
||||||
ip_length += _strlen(temp) + 1;
|
|
||||||
|
|
||||||
new_splice_command = (char *)realloc(splice_command, ip_length + 32);
|
|
||||||
if (new_splice_command == NULL) {
|
|
||||||
free(splice_command);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
splice_command = new_splice_command;
|
|
||||||
|
|
||||||
//printf(RED"Hello World\n"COLOR_NONE);
|
|
||||||
printf(RED "%s Illegal IP: %s\n" COLOR_NONE, t, temp);
|
|
||||||
strcat(splice_command, temp);
|
|
||||||
strcat(splice_command, "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("%s", splice_command); // 打印所有非法IP
|
|
||||||
//printf("%ld\n", ip_length);
|
|
||||||
|
|
||||||
command = (char *)malloc(ip_length + BUFFER);
|
|
||||||
if (command == NULL) {
|
|
||||||
free(command);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memset(command, 0, ip_length + BUFFER);
|
|
||||||
|
|
||||||
snprintf(awk, BUFFER, AWK, conf->REFUSE_NUMBER); // 拼接命令
|
|
||||||
memcpy(command, "echo \"", 7);
|
|
||||||
strcat(command, splice_command);
|
|
||||||
strcat(command, "\"");
|
|
||||||
strcat(command, awk);
|
|
||||||
|
|
||||||
if ((fc = popen(command, "r")) == NULL) // 执行命令
|
|
||||||
{
|
|
||||||
perror("popen command");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (splice_command != NULL) {
|
|
||||||
free(splice_command);
|
|
||||||
}
|
|
||||||
if (command != NULL) {
|
|
||||||
free(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (fgets(buffer, BUFFER, fc) != NULL) // 执行命令后, 为空时就不会
|
|
||||||
{
|
|
||||||
buffer[_strlen(buffer) - 1] = '\0'; // 去除回车
|
|
||||||
|
|
||||||
memset(REGION_LIST_COPY, 0, conf->REGION_LIST_LEN + 1);
|
|
||||||
memset(IPV4_WHITE_LIST_COPY, 0, conf->IPV4_WHITE_LIST_LEN + 1);
|
|
||||||
|
|
||||||
memcpy(REGION_LIST_COPY, conf->REGION_LIST, conf->REGION_LIST_LEN); // 复制配置字符串,split_string()会改变原数据
|
|
||||||
memcpy(IPV4_WHITE_LIST_COPY, conf->IPV4_WHITE_LIST, conf->IPV4_WHITE_LIST_LEN); //
|
|
||||||
|
|
||||||
split_string(IPV4_WHITE_LIST_COPY, " ", whitelist_ip);
|
|
||||||
split_string(REGION_LIST_COPY, " ", region_list);
|
|
||||||
|
|
||||||
if (conf->IPV4_RESTRICTION == 1) // 是否启用白名单
|
|
||||||
{
|
|
||||||
if (whitelist(buffer, whitelist_ip) == 1) {
|
|
||||||
printf("%s 白名单IPV4:%s\n", t, buffer);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != show_all_rule(buffer)) // libiptc库判断否存在规则
|
|
||||||
{
|
|
||||||
char *location_json = NULL;
|
|
||||||
char *area = NULL;
|
|
||||||
char URL[conf->REGION_URL_LEN + 32];
|
|
||||||
char *xdb_path = "ip2region.xdb";
|
|
||||||
|
|
||||||
// 地域白名单
|
|
||||||
if (conf->REGION == 1) {
|
|
||||||
memset(URL, 0, conf->REGION_URL_LEN + 32);
|
|
||||||
snprintf(URL, conf->REGION_URL_LEN + 32, conf->REGION_URL, buffer);
|
|
||||||
|
|
||||||
if (conf->IP2REGION == 1) { // ip2region 地址定位库
|
|
||||||
printf("%s Use ip2region !!!\n", t);
|
|
||||||
|
|
||||||
if (-1 == access(xdb_path, F_OK)) // 判断 ip2region 地址定位库是否存在
|
|
||||||
{
|
|
||||||
xdb_path = "ip2region/ip2region.xdb";
|
|
||||||
|
|
||||||
if (-1 == access(xdb_path, F_OK)) {
|
|
||||||
printf("%s ip2region.xdb DOESN'T EXISIT!\n", t);
|
|
||||||
goto AREA;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
area = ip2region(xdb_path, buffer);
|
|
||||||
if (area == NULL) {
|
|
||||||
printf("%s ip2region解析地域错误\n", t);
|
|
||||||
goto BLOCKED;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
AREA:
|
|
||||||
location_json = GET_PUBLIC_IP(URL);
|
|
||||||
if (location_json == NULL) {
|
|
||||||
printf("%s 获取地域错误\n", t);
|
|
||||||
goto BLOCKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
area = process_json(location_json, conf->REGION_URL);
|
|
||||||
if (area == NULL) {
|
|
||||||
printf("%s 解析地域错误\n", t);
|
|
||||||
goto BLOCKED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isregion(area, region_list) == 1) {
|
|
||||||
printf(RED "%s Ip Address: %s, 地域白名单: %s\n" COLOR_NONE, t, buffer, area);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
printf(RED "%s 攻击者IP地址:%s, %s\n" COLOR_NONE, t, buffer, area);
|
|
||||||
|
|
||||||
if (conf->IS_DING_WEBHOOK == 1) // 钉钉告警
|
|
||||||
{
|
|
||||||
dingding_warning(area, public_ip, buffer, conf);
|
|
||||||
sleep(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conf->IS_MAIL == 1) // 邮件告警
|
|
||||||
{
|
|
||||||
mail_warning(area, public_ip, buffer, conf);
|
|
||||||
sleep(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conf->IS_QQMAIL == 1) // 邮件告警
|
|
||||||
{
|
|
||||||
QQ_mail_warning(area, public_ip, buffer, conf);
|
|
||||||
sleep(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
BLOCKED:
|
|
||||||
// 是否封禁攻击IP
|
|
||||||
if (conf->IS_BLOCKED == 1) {
|
|
||||||
// libiptc 库插入规则
|
|
||||||
// iptables -t filter -A INPUT -p tcp -m tcp -s 47.110.180.35 -j DROP
|
|
||||||
|
|
||||||
// libiptc 库删除规则
|
|
||||||
// iptables -t filter -D INPUT -p tcp -m tcp -s 47.110.180.35 -j DROP
|
|
||||||
unsigned int srcIp;
|
|
||||||
inet_pton(AF_INET, buffer, &srcIp);
|
|
||||||
iptc_add_rule("filter", "INPUT", IPPROTO_TCP, NULL, NULL, srcIp, 0, NULL, NULL, "DROP", NULL, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (location_json != NULL)
|
|
||||||
free(location_json);
|
|
||||||
if (area != NULL)
|
|
||||||
free(area);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fp != NULL)
|
|
||||||
pclose(fp);
|
|
||||||
if (fc != NULL)
|
|
||||||
pclose(fc);
|
|
||||||
if (t)
|
|
||||||
free(t);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sig_child(int signo)
|
static void sig_child(int signo)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
@ -769,7 +77,6 @@ static void sig_child(int signo)
|
|||||||
|
|
||||||
static int get_executable_path(char *processdir, char *processname, int len)
|
static int get_executable_path(char *processdir, char *processname, int len)
|
||||||
{
|
{
|
||||||
|
|
||||||
char *processname_ptr;
|
char *processname_ptr;
|
||||||
|
|
||||||
if (readlink("/proc/self/exe", processdir, len) <= 0)
|
if (readlink("/proc/self/exe", processdir, len) <= 0)
|
||||||
@ -786,9 +93,9 @@ static int get_executable_path(char *processdir, char *processname, int len)
|
|||||||
// 处理参数
|
// 处理参数
|
||||||
int process_argv(int argc, char *argv[], char **argvs)
|
int process_argv(int argc, char *argv[], char **argvs)
|
||||||
{
|
{
|
||||||
|
int i=0, j=0;
|
||||||
argvs[0] = argv[0];
|
argvs[0] = argv[0];
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
for (i = 0; i <= argc - 1; i++) {
|
for (i = 0; i <= argc - 1; i++) {
|
||||||
if (i == 1) {
|
if (i == 1) {
|
||||||
for (j = i; j <= argc - 2; j++) {
|
for (j = i; j <= argc - 2; j++) {
|
||||||
@ -836,13 +143,11 @@ static int get_clamav_log(char *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (fgets(buffer, BUFFER, fp) != NULL) {
|
while (fgets(buffer, BUFFER, fp) != NULL) {
|
||||||
//printf("%s", buffer);
|
|
||||||
temp = strstr(buffer, "Infected");
|
temp = strstr(buffer, "Infected");
|
||||||
if (temp)
|
if (temp)
|
||||||
sscanf(temp, "Infected files: %32s", temp);
|
sscanf(temp, "Infected files: %32s", temp);
|
||||||
|
|
||||||
if (temp != NULL) {
|
if (temp != NULL) {
|
||||||
//printf("%s\n", temp);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -953,7 +258,6 @@ static char help_information(void)
|
|||||||
|
|
||||||
int main(int argc, char *argv[], char **env)
|
int main(int argc, char *argv[], char **env)
|
||||||
{
|
{
|
||||||
|
|
||||||
signal(SIGCHLD, sig_child); // 创建捕捉子进程退出信号
|
signal(SIGCHLD, sig_child); // 创建捕捉子进程退出信号
|
||||||
|
|
||||||
int pid;
|
int pid;
|
||||||
@ -1043,15 +347,15 @@ int main(int argc, char *argv[], char **env)
|
|||||||
head_argc += 1;
|
head_argc += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// 打印clamav参数
|
// 打印clamav参数
|
||||||
for(int i=0; i<head_argc; i++)
|
for(int i=0; i<head_argc; i++)
|
||||||
{
|
{
|
||||||
printf("%s %d\n", head_argvs[i], i);
|
printf("%s %d\n", head_argvs[i], i);
|
||||||
}
|
}
|
||||||
|
|
||||||
_clamscan(head_argc, head_argvs);
|
_clamscan(head_argc, head_argvs);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
now_next_time *t = (now_next_time *) malloc(sizeof(struct now_next_time));
|
now_next_time *t = (now_next_time *) malloc(sizeof(struct now_next_time));
|
||||||
memset(t, 0, sizeof(struct now_next_time));
|
memset(t, 0, sizeof(struct now_next_time));
|
||||||
@ -1061,11 +365,11 @@ int main(int argc, char *argv[], char **env)
|
|||||||
//printf("%s", public_ip);
|
//printf("%s", public_ip);
|
||||||
|
|
||||||
if (0 == strcmp(conf->DAEMON, "on")) {
|
if (0 == strcmp(conf->DAEMON, "on")) {
|
||||||
goto goto_daemon;
|
goto DAEMON;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv[1] != NULL && 0 == strcmp(argv[1], "-d")) {
|
if (argv[1] != NULL && 0 == strcmp(argv[1], "-d")) {
|
||||||
goto_daemon:
|
DAEMON:
|
||||||
|
|
||||||
// 守护进程
|
// 守护进程
|
||||||
if ((pid = fork()) < 0) {
|
if ((pid = fork()) < 0) {
|
||||||
@ -1105,18 +409,40 @@ goto_daemon:
|
|||||||
if (-1 == (nice(-20)))
|
if (-1 == (nice(-20)))
|
||||||
perror("nice");
|
perror("nice");
|
||||||
|
|
||||||
|
|
||||||
// 处理Nginx
|
// 处理Nginx
|
||||||
pid_t pid = fork(); // 创建子进程
|
if (conf->NGINX == 1) {
|
||||||
if (pid == 0) {
|
pid_t pid = fork(); // 创建子进程
|
||||||
printf("The parent process processes Nginx logs!!!\n");
|
if (pid == 0) {
|
||||||
while (1)
|
printf("Nginx process!!!\n");
|
||||||
{
|
while (1)
|
||||||
nginx_read_log(conf->NGINX_LOG_FILE, conf);
|
{
|
||||||
sleep(1);
|
nginx_read_log(conf->NGINX_LOG_FILE, conf);
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理SSH
|
||||||
|
if (conf->IS_BLOCKED == 1) {
|
||||||
|
pid_t pid = fork(); // 创建子进程
|
||||||
|
if (pid == 0) {
|
||||||
|
printf("SSH process!!!\n");
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (DEBISN_SYSTEM == check_system()) {
|
||||||
|
rule_(conf, "/var/log/auth.log");
|
||||||
|
}
|
||||||
|
if (CENTOS_SYSTEM == check_system()) {
|
||||||
|
rule_(conf, "/var/log/secure");
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clamscan
|
||||||
|
printf("Clamscan process!!!\n");
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
// Cron
|
// Cron
|
||||||
@ -1178,39 +504,28 @@ goto_daemon:
|
|||||||
|
|
||||||
// 磁盘告警
|
// 磁盘告警
|
||||||
if (1 == conf->IS_DISK) {
|
if (1 == conf->IS_DISK) {
|
||||||
if (disk_waring(conf->DISK_USE) == 1) {
|
disk_usage(conf, public_ip, conf->DISK_USE);
|
||||||
printf("Disk usage reaches threshold!, Please handle!\n");
|
|
||||||
if (conf->IS_QQMAIL == 1) {
|
|
||||||
QQ_mail_warning_Disk_Use(public_ip, 0, conf);
|
|
||||||
sleep(3);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
printf("Disk usage does not reach threshold!\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_exit(r);
|
|
||||||
|
|
||||||
|
_exit(r);
|
||||||
} else {
|
} else {
|
||||||
int status = 0;
|
int status = 0;
|
||||||
wait(&status); // wait the end of child process
|
wait(&status); // wait the end of child process
|
||||||
if (WIFEXITED(status)) {
|
if (WIFEXITED(status)) {
|
||||||
;
|
;
|
||||||
//printf("child process return %d\n", WEXITSTATUS(status));
|
printf("child process return %d\n", WEXITSTATUS(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep(60); // 跳过这一分钟
|
sleep(60); // 跳过这一分钟
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 封禁非法IP
|
|
||||||
rule(conf);
|
|
||||||
sleep(conf->TIME);
|
|
||||||
|
|
||||||
|
sleep(conf->TIME);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
free(t);
|
free(t);
|
||||||
free_conf(conf);
|
free_conf(conf);
|
||||||
free(conf);
|
free(conf);
|
||||||
|
24
rhost.conf
24
rhost.conf
@ -1,47 +1,37 @@
|
|||||||
global {
|
global {
|
||||||
|
|
||||||
DAEMON = "off"; // on开启后台运行,off不开启(弃用)
|
DAEMON = "off"; // on开启后台运行,off不开启(弃用)
|
||||||
TIME = "10"; // 睡眠时间(大于等于1,单位秒)
|
TIME = "1"; // 睡眠时间(大于等于1,单位秒)
|
||||||
|
|
||||||
|
|
||||||
PUBLIC_IP = "http://inet-ip.info"; // 获取公网IP
|
PUBLIC_IP = "http://inet-ip.info"; // 获取公网IP
|
||||||
|
|
||||||
|
|
||||||
IS_DISK = 1; // 磁盘使用率(1开启,非1关闭)
|
IS_DISK = 1; // 磁盘使用率(1开启,非1关闭)
|
||||||
DISK_USE = 95; // 任意某块磁盘使用率告警(大于等于1)
|
DISK_USE = 50; // 任意某块磁盘使用率告警(大于等于1)
|
||||||
|
|
||||||
|
|
||||||
IS_BLOCKED = 1; // 是否封禁攻击IP(1开启,非1关闭)
|
IS_BLOCKED = 1; // 是否封禁攻击IP(1开启,非1关闭)
|
||||||
REFUSE_NUMBER = 3; // 拒绝攻击次数
|
|
||||||
|
|
||||||
|
IS_MAIL = 0; // 开启邮件告警(1开启,非1关闭)
|
||||||
|
|
||||||
CLAMAV = 1; // clamav 是否扫描病毒(1开启,非1关闭)
|
CLAMAV = 1; // clamav 是否扫描病毒(1开启,非1关闭)
|
||||||
CLAMAV_ARG = "-r / --exclude-dir=^/sys|^/dev|^/proc|^/opt/infected|^/root|^/home|^/mnt|^/usr|^/var --move=/opt/infected --max-filesize 1024M -l clamscan.log";
|
CLAMAV_ARG = "-r / --exclude-dir=^/sys|^/dev|^/proc|^/opt/infected|^/root|^/home|^/mnt|^/usr|^/var --move=/opt/infected --max-filesize 1024M -l clamscan.log";
|
||||||
CLAMAV_TIME = "* 45 11 * * *"; // clamav 扫描时间(Cron格式, 秒 分 时 天 月 周)
|
CLAMAV_TIME = "* 45 11 * * *"; // clamav 扫描时间(Cron格式, 秒 分 时 天 月 周)
|
||||||
|
|
||||||
|
|
||||||
IPV4_RESTRICTION = 1; // 是否启用IP白名单(1开启,非1关闭)
|
IPV4_RESTRICTION = 1; // 是否启用IP白名单(1开启,非1关闭)
|
||||||
IPV4_WHITE_LIST = "1.1.1.1 2.2.2.2 "; // IP白名单(空格隔开)
|
IPV4_WHITE_LIST = "1.1.1.1 2.2.2.2 "; // IP白名单(空格隔开)
|
||||||
|
|
||||||
|
|
||||||
REGION = 1; // 是否启用地域白名单(1开启,非1关闭)
|
REGION = 1; // 是否启用地域白名单(1开启,非1关闭)
|
||||||
IP2REGION = 1; // 是否使用本地 ip2region 地址定位库(1使用,非1不使用)
|
IP2REGION = 1; // 是否使用本地 ip2region 地址定位库(1使用,非1不使用)
|
||||||
REGION_LIST = "河南 郑州 上海"; // 地域列表(空格隔开)
|
REGION_LIST = "河南 郑州 上海"; // 地域列表(空格隔开)
|
||||||
|
|
||||||
|
|
||||||
NGINX = 1; // 是否启用Nginx白名单
|
NGINX = 1; // 是否启用Nginx白名单
|
||||||
NGINX_LOG_FILE= "/usr/local/nginx/logs/access.log"; // Nginx 日志文件
|
#NGINX_LOG_FILE= "/var/log/nginx/access.log"; // Nginx 日志文件
|
||||||
NGINX_REGION_LIST = "中国 河南 郑州 上海"; // 地域列表(空格隔开)
|
NGINX_LOG_FILE= "/opt/nginx/logs/access.log"; // Nginx 日志文件
|
||||||
|
NGINX_REGION_LIST = "中国 河南 郑州 上海 内网"; // 地域列表(空格隔开)
|
||||||
|
|
||||||
IS_MAIL = 0; // 开启邮件告警(1开启,非1关闭)
|
|
||||||
|
|
||||||
|
|
||||||
IS_DING_WEBHOOK = 1; // 开启叮叮告警(1开启,非1关闭)
|
IS_DING_WEBHOOK = 1; // 开启叮叮告警(1开启,非1关闭)
|
||||||
PHONE = "15565979082"; // @的人手机号
|
PHONE = "15565979082"; // @的人手机号
|
||||||
DING_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=396bce0384cded025087cff3c176ea5e9afb9bd8fcaa46d6fa8c51dd172ba513"; // 钉钉WEBHOOK
|
DING_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=396bce0384cded025087cff3c176ea5e9afb9bd8fcaa46d6fa8c51dd172ba513"; // 钉钉WEBHOOK
|
||||||
|
|
||||||
|
|
||||||
IS_QQMAIL = 1; // 开启QQ邮箱告警(默认使用gomail: https://git.aixiao.me/aixiao/gomail.git)(1开启,非1关闭)
|
IS_QQMAIL = 1; // 开启QQ邮箱告警(默认使用gomail: https://git.aixiao.me/aixiao/gomail.git)(1开启,非1关闭)
|
||||||
RECV_MAIL = "1605227279@qq.com"; // 接收者邮箱
|
RECV_MAIL = "1605227279@qq.com"; // 接收者邮箱
|
||||||
}
|
}
|
||||||
|
18
rhost.h
18
rhost.h
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
||||||
|
|
||||||
typedef struct now_next_time
|
typedef struct now_next_time
|
||||||
{
|
{
|
||||||
int now_year;
|
int now_year;
|
||||||
@ -40,22 +39,17 @@ typedef struct now_next_time
|
|||||||
} now_next_time;
|
} now_next_time;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define COLOR_NONE "\033[0m" //表示清除前面设置的格式
|
#define COLOR_NONE "\033[0m" //表示清除前面设置的格式
|
||||||
#define RED "\033[1;31;40m" //40表示背景色为黑色, 1 表示高亮
|
#define RED "\033[1;31;40m" //40表示背景色为黑色, 1 表示高亮
|
||||||
#define BLUE "\033[1;34;40m"
|
#define BLUE "\033[1;34;40m"
|
||||||
#define GREEN "\033[1;32;40m"
|
#define GREEN "\033[1;32;40m"
|
||||||
#define YELLOW "\033[1;33;40m"
|
#define YELLOW "\033[1;33;40m"
|
||||||
|
|
||||||
|
|
||||||
#define CENTOS_SYSTEM 1
|
#define CENTOS_SYSTEM 1
|
||||||
#define DEBISN_SYSTEM 2
|
#define DEBISN_SYSTEM 2
|
||||||
#define UNKNOWN_SYSTEM 3
|
#define UNKNOWN_SYSTEM 3
|
||||||
|
|
||||||
#define BUFFER 1024
|
#define BUFFER 1024
|
||||||
#define LONG_BUFFER 1024*1000
|
|
||||||
#define ARGS_NUM 20
|
#define ARGS_NUM 20
|
||||||
#define WHITELIST_IP_NUM 1024
|
#define WHITELIST_IP_NUM 1024
|
||||||
#define BUILD(fmt...) do { fprintf(stderr,"%s %s ",__DATE__,__TIME__); fprintf(stderr, ##fmt); } while(0)
|
#define BUILD(fmt...) do { fprintf(stderr,"%s %s ",__DATE__,__TIME__); fprintf(stderr, ##fmt); } while(0)
|
||||||
@ -67,19 +61,7 @@ typedef struct now_next_time
|
|||||||
#define CENTOS_GE_10 "grep -E \"^$(LC_ALL=\"C\" date \"+%h\").$(LC_ALL=\"C\" date \"+%d\")\" /var/log/secure | grep failure | grep rhost"
|
#define CENTOS_GE_10 "grep -E \"^$(LC_ALL=\"C\" date \"+%h\").$(LC_ALL=\"C\" date \"+%d\")\" /var/log/secure | grep failure | grep rhost"
|
||||||
#define CENTOS_LE_10 "grep -E \"^$(LC_ALL=\"C\" date \"+%h\")..$(LC_ALL=\"C\" date | awk '{print $3}')\" /var/log/secure | grep failure | grep rhost"
|
#define CENTOS_LE_10 "grep -E \"^$(LC_ALL=\"C\" date \"+%h\")..$(LC_ALL=\"C\" date | awk '{print $3}')\" /var/log/secure | grep failure | grep rhost"
|
||||||
|
|
||||||
#define QQMAIL "gomail -r %s -s \"System ban IP\" -t \"%s\""
|
|
||||||
|
|
||||||
#define QQMAIL_Virus "gomail -r %s -s \"System Virus Infected\" -t \"%s\""
|
|
||||||
#define QQMAIL_DISK_USE "gomail -r %s -s \"System Disk Use\" -t \"%s\""
|
|
||||||
|
|
||||||
#define LOG_FILE "nginx.log"
|
|
||||||
|
|
||||||
|
|
||||||
extern void read_conf(char *filename, conf * configure);
|
|
||||||
extern void free_conf(conf * conf);
|
|
||||||
extern void ptintf_conf(conf * conf);
|
|
||||||
extern void my_printf(const char *format, ...);
|
|
||||||
extern char *_time();
|
|
||||||
extern int isregion(char *str, char (*region_list)[WHITELIST_IP_NUM]);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
147
rule.c
Normal file
147
rule.c
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
#include "rule.h"
|
||||||
|
|
||||||
|
|
||||||
|
static int Handle_IP(conf *conf, char *ip)
|
||||||
|
{
|
||||||
|
char whitelist_ip[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } };
|
||||||
|
char region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } };
|
||||||
|
char REGION_LIST_COPY[conf->REGION_LIST_LEN + 1];
|
||||||
|
char IPV4_WHITE_LIST_COPY[conf->IPV4_WHITE_LIST_LEN + 1];
|
||||||
|
char *t = _time();
|
||||||
|
|
||||||
|
memset(REGION_LIST_COPY, 0, sizeof(REGION_LIST_COPY));
|
||||||
|
memset(IPV4_WHITE_LIST_COPY, 0, sizeof(IPV4_WHITE_LIST_COPY));
|
||||||
|
|
||||||
|
memcpy(REGION_LIST_COPY, conf->REGION_LIST, strlen(conf->REGION_LIST));
|
||||||
|
memcpy(IPV4_WHITE_LIST_COPY, conf->IPV4_WHITE_LIST, strlen(conf->IPV4_WHITE_LIST));
|
||||||
|
|
||||||
|
split_string(IPV4_WHITE_LIST_COPY, " ", whitelist_ip);
|
||||||
|
split_string(REGION_LIST_COPY, " ", region_list);
|
||||||
|
|
||||||
|
// IP白名单
|
||||||
|
if (conf->IPV4_RESTRICTION == 1) {
|
||||||
|
if (whitelist(ip, whitelist_ip) == 1) {
|
||||||
|
printf("%s 白名单IPV4:%s\n", t, ip);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_all_rule(ip) != 0) // 不在防火墙规则表里
|
||||||
|
{
|
||||||
|
char *area = NULL;
|
||||||
|
char *xdb_path = "ip2region.xdb";
|
||||||
|
|
||||||
|
if (conf->REGION == 1) {
|
||||||
|
if (conf->IP2REGION == 1) {
|
||||||
|
//printf("%s Use ip2region !!!\n", t);
|
||||||
|
|
||||||
|
if (access(xdb_path, F_OK) == -1) {
|
||||||
|
xdb_path = "ip2region/ip2region.xdb";
|
||||||
|
if (access(xdb_path, F_OK) == -1) {
|
||||||
|
printf("%s ip2region.xdb DOESN'T EXIST!\n", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
area = ip2region(xdb_path, ip);
|
||||||
|
if (area == NULL) {
|
||||||
|
printf("%s ip2region解析地域错误\n", t);
|
||||||
|
goto BLOCKED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isregion(area, region_list) == 1) {
|
||||||
|
printf(RED "%s SSH Ip Address: %s, 地域白名单: %s\n" COLOR_NONE, t, ip, area);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(RED "%s 攻击者IP地址:%s, %s\n" COLOR_NONE, t, ip, area);
|
||||||
|
|
||||||
|
BLOCKED:
|
||||||
|
if (conf->IS_BLOCKED == 1) {
|
||||||
|
unsigned int srcIp;
|
||||||
|
inet_pton(AF_INET, ip, &srcIp);
|
||||||
|
iptc_add_rule("filter", "INPUT", IPPROTO_TCP, NULL, NULL, srcIp, 0, NULL, NULL, "DROP", NULL, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (area != NULL) {
|
||||||
|
free(area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void extract_rhost_ip(conf *conf, const char *line) {
|
||||||
|
char *rhost_start = strstr(line, RHOST_KEY);
|
||||||
|
if (rhost_start) {
|
||||||
|
rhost_start += strlen(RHOST_KEY); // 移动到rhost=后的字符
|
||||||
|
char *rhost_end = strpbrk(rhost_start, " \n");
|
||||||
|
if (rhost_end) {
|
||||||
|
char ip[64];
|
||||||
|
strncpy(ip, rhost_start, rhost_end - rhost_start);
|
||||||
|
ip[rhost_end - rhost_start] = '\0';
|
||||||
|
|
||||||
|
Handle_IP(conf, ip);
|
||||||
|
} else {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rule_(conf *conf, char *LOG_FILE) {
|
||||||
|
FILE *file;
|
||||||
|
char buffer[BUFFER_SIZE];
|
||||||
|
off_t last_size = 0;
|
||||||
|
struct stat file_stat;
|
||||||
|
|
||||||
|
// 打开日志文件
|
||||||
|
file = fopen(LOG_FILE, "r");
|
||||||
|
if (file == NULL) {
|
||||||
|
perror("无法打开日志文件");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取文件初始大小
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
last_size = ftell(file);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// 检查文件是否被轮转
|
||||||
|
if (stat(LOG_FILE, &file_stat) == -1) {
|
||||||
|
perror("无法获取文件状态");
|
||||||
|
fclose(file);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果文件大小小于上次读取的位置,说明文件被轮转了
|
||||||
|
if (file_stat.st_size < last_size) {
|
||||||
|
fclose(file);
|
||||||
|
file = fopen(LOG_FILE, "r");
|
||||||
|
if (file == NULL) {
|
||||||
|
perror("无法重新打开日志文件");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
last_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移动到上次读取的位置
|
||||||
|
fseek(file, last_size, SEEK_SET);
|
||||||
|
|
||||||
|
// 逐行读取新增的日志内容
|
||||||
|
while (fgets(buffer, sizeof(buffer), file) != NULL) {
|
||||||
|
extract_rhost_ip(conf, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录当前文件大小
|
||||||
|
last_size = ftell(file);
|
||||||
|
|
||||||
|
// 暂停一段时间然后继续检查文件变化
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭文件
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
26
rule.h
Normal file
26
rule.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef RULE_H
|
||||||
|
#define RULE_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "rhost.h"
|
||||||
|
#include "conf.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "libiptc.h"
|
||||||
|
#include "ip2region/ip2region.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define RHOST_KEY "rhost="
|
||||||
|
#define BUFFER_SIZE 1024
|
||||||
|
#define WHITELIST_IP_NUM 1024
|
||||||
|
|
||||||
|
extern int rule_(conf *conf, char *LOG_FILE);
|
||||||
|
|
||||||
|
#endif
|
136
warning.c
Normal file
136
warning.c
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#include "warning.h"
|
||||||
|
|
||||||
|
// 钉钉告警
|
||||||
|
int dingding_warning(char *illegal_ip, char *public_ip, char *ip, conf *conf)
|
||||||
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
|
char temp[64];
|
||||||
|
char jsonObj[BUFFER];
|
||||||
|
|
||||||
|
memset(jsonObj, 0, BUFFER);
|
||||||
|
memset(temp, 0, 64);
|
||||||
|
strcpy(temp, public_ip);
|
||||||
|
temp[_strlen(public_ip) - 1] = '\0';
|
||||||
|
|
||||||
|
if ((fp = fopen("libcurl.log", "wt+")) == NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CURL *curl;
|
||||||
|
CURLcode res;
|
||||||
|
|
||||||
|
curl_global_init(CURL_GLOBAL_ALL);
|
||||||
|
curl = curl_easy_init();
|
||||||
|
if (curl == NULL) {
|
||||||
|
fclose(fp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#define JSIN "{ \
|
||||||
|
\"msgtype\": \"text\", \
|
||||||
|
\"text\": { \
|
||||||
|
\"content\": \"Alert @%s 服务器地址:%s,封禁非法入侵主机:(%s%s)\" \
|
||||||
|
}, \
|
||||||
|
\"at\": { \
|
||||||
|
\"atMobiles\": [\"%s\"], \
|
||||||
|
\"isAtAll\": false \
|
||||||
|
} \
|
||||||
|
}"
|
||||||
|
|
||||||
|
snprintf(jsonObj, BUFFER, JSIN, conf->PHONE, temp, ip, illegal_ip, conf->PHONE);
|
||||||
|
printf("%s\n", jsonObj);
|
||||||
|
|
||||||
|
struct curl_slist *headers = NULL;
|
||||||
|
headers = curl_slist_append(headers, "Accept: application/json");
|
||||||
|
headers = curl_slist_append(headers, "Content-Type: application/json");
|
||||||
|
headers = curl_slist_append(headers, "charset: utf-8");
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, conf->DING_WEBHOOK);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonObj);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl/0.1");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
|
||||||
|
|
||||||
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
curl_global_cleanup();
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 邮件告警
|
||||||
|
int mail_warning(char *illegal_ip, char *public_ip, char *ip, conf *conf)
|
||||||
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
|
char text[BUFFER];
|
||||||
|
char temp[64];
|
||||||
|
|
||||||
|
// 初始化缓冲区
|
||||||
|
memset(text, 0, BUFFER);
|
||||||
|
memset(temp, 0, 64);
|
||||||
|
|
||||||
|
// 复制和处理public_ip
|
||||||
|
strncpy(temp, public_ip, sizeof(temp) - 1);
|
||||||
|
temp[_strlen(public_ip) - 1] = '\0';
|
||||||
|
|
||||||
|
// 构建邮件发送命令
|
||||||
|
snprintf(text, BUFFER, "echo \"主机:%s, 禁止(%s%s)访问\" | mail -s \"System ban IP\" %s", temp, ip, illegal_ip, conf->RECV_MAIL);
|
||||||
|
|
||||||
|
// 使用popen发送邮件
|
||||||
|
if (NULL == (fp = popen(text, "r"))) {
|
||||||
|
perror("popen text");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭文件指针
|
||||||
|
if (NULL != fp && pclose(fp) == -1) {
|
||||||
|
perror("pclose");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第三方邮箱告警
|
||||||
|
int QQ_mail_warning(char *illegal_ip, char *public_ip, char *ip, conf *conf)
|
||||||
|
{
|
||||||
|
char string[BUFFER + (sizeof(QQMAIL)) + 1];
|
||||||
|
char text[BUFFER];
|
||||||
|
char temp[32];
|
||||||
|
|
||||||
|
memset(string, 0, BUFFER + (sizeof(QQMAIL)) + 1);
|
||||||
|
memset(text, 0, BUFFER);
|
||||||
|
memset(temp, 0, 32);
|
||||||
|
strcpy(temp, public_ip);
|
||||||
|
temp[_strlen(public_ip) - 1] = '\0';
|
||||||
|
|
||||||
|
snprintf(text, BUFFER, "主机:%s, 禁止(%s%s)访问!", temp, ip, illegal_ip);
|
||||||
|
snprintf(string, BUFFER + (sizeof(QQMAIL)) + 1, QQMAIL, conf->RECV_MAIL, text);
|
||||||
|
|
||||||
|
return system(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第三方邮箱告警, 感染病毒邮件提醒
|
||||||
|
int QQ_mail_warning_Virus_files(char *local_ip, int Virus_number, conf *conf)
|
||||||
|
{
|
||||||
|
char *command;
|
||||||
|
char *text;
|
||||||
|
char temp[32];
|
||||||
|
|
||||||
|
command = (char *)alloca(BUFFER + (sizeof(QQMAIL)) + 1);
|
||||||
|
text = (char *)alloca(BUFFER);
|
||||||
|
memset(command, 0, BUFFER + (sizeof(QQMAIL)) + 1);
|
||||||
|
memset(text, 0, BUFFER);
|
||||||
|
memset(temp, 0, 32);
|
||||||
|
|
||||||
|
strcpy(temp, local_ip);
|
||||||
|
temp[_strlen(local_ip) - 1] = '\0';
|
||||||
|
snprintf(text, BUFFER, "Host:%s, Infected files: %d, Please handle!", temp, Virus_number);
|
||||||
|
snprintf(command, BUFFER + BUFFER + (sizeof(QQMAIL)) + 1, QQMAIL_Virus, conf->RECV_MAIL, text);
|
||||||
|
|
||||||
|
return system(command);
|
||||||
|
}
|
32
warning.h
Normal file
32
warning.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef WARNING_H
|
||||||
|
#define WARNING_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "conf.h"
|
||||||
|
|
||||||
|
#define BUFFER 1024
|
||||||
|
#define QQMAIL "gomail -r %s -s \"System ban IP\" -t \"%s\""
|
||||||
|
#define QQMAIL_Virus "gomail -r %s -s \"System Virus Infected\" -t \"%s\""
|
||||||
|
#define QQMAIL_DISK_USE "gomail -r %s -s \"System Disk Use\" -t \"%s\""
|
||||||
|
|
||||||
|
extern int dingding_warning(char *illegal_ip, char *public_ip, char *ip, conf *conf);
|
||||||
|
extern int mail_warning(char *illegal_ip, char *public_ip, char *ip, conf *conf);
|
||||||
|
extern int QQ_mail_warning(char *illegal_ip, char *public_ip, char *ip, conf *conf);
|
||||||
|
extern int QQ_mail_warning_Virus_files(char *local_ip, int Virus_number, conf *conf);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user