增加告警、优化

This commit is contained in:
aixiao 2022-06-26 19:49:00 +08:00
parent 86d7bf5780
commit 13d417727c
6 changed files with 331 additions and 35 deletions

View File

@ -1,11 +1,11 @@
CROSS_COMPILE ?=
CC := $(CROSS_COMPILE)gcc
CFLAGS += -O2 -g -Wall
CFLAGS += -g -Wall
LIB += -lcurl
OBG = rhost
all: rhost.o
$(CC) $(CFLAGS) $^ -o $(OBG)
$(CC) $(CFLAGS) $^ -o $(OBG) $(LIB)
clean:
rm -rf *.o

View File

@ -1,8 +1,11 @@
# denyhosts
ssh防止暴力破解,适用Debian 8、9
支持钉钉告警和邮件告警
支持第三方QQ邮箱告警
支持一次运行检测、后台运行检测
请安装libcurl库
## Help Information
cd /root
git clone https://github.com/niuyuling/denyhosts.git
cd denyhosts
@ -12,3 +15,5 @@ chmod a+x /root/denyhosts/denyhosts.sh
crontab 定时任务,像这样.
0 22 * * * /root/denyhosts/denyhosts.sh

View File

@ -42,6 +42,7 @@ function run()
mail -s "System Log" ${email_address} < ${log_file}
rm ${log_file}
fi
sync
}

BIN
rhost

Binary file not shown.

320
rhost.c
View File

@ -4,19 +4,212 @@
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
#include <curl/curl.h>
#define BUFFER 270
#define CENTOS_SYSTEM 1
#define DEBISN_SYSTEM 2
#define UNKNOWN_SYSTEM 3
#define BUFFER 1024
#define LONG_BUFFER 1024*100
#define TOP_IP 20
#define AWK "| awk -v num=%d '{a[$1]+=1;} END {for(i in a){if (a[i] >= num) {print i;}}}' "
#define GE_10 "grep -E \"^$(date \"+%h\").$(date \"+%d\")\" /var/log/auth.log | grep failure | grep rhost"
#define LE_10 "grep -E \"^$(date \"+%h\")..$(date | awk '{print $3}')\" /var/log/auth.log | grep failure | grep rhost"
#define IPTABLES "/sbin/iptables -I INPUT -s %s -j DROP"
#define TOP_IP 10
#define AWK " | awk -v num=%d '{a[$1]+=1;} END {for(i in a){if (a[i] >= num) {print i;}}}' "
#define GE_10 "grep -E \"^$(LC_ALL=\"C\" date \"+%h\").$(LC_ALL=\"C\" date \"+%d\")\" /var/log/auth.log | grep failure | grep rhost"
#define LE_10 "grep -E \"^$(LC_ALL=\"C\" date \"+%h\")..$(LC_ALL=\"C\" date | awk '{print $3}')\" /var/log/auth.log | grep failure | grep rhost"
int main(int argc, char *argv[], char **env)
#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 IPTABLES "iptables -I INPUT -s %s -j DROP"
#define IPTABLES_CHECK "iptables -C INPUT -s %s -j DROP"
#define TIME 60
#define IS_DIND 1
#define PHONE "155659790"
#define DING_CURL "https://oapi.dingtalk.com/robot/send?access_token=7f069c672cb878987aa6772cca336740eece4ce36bde12b51b45e9f440e"
#define IS_MAIL 0
#define IS_QQMAIL 0
#define QQMAIL "qqMail -l smtp.qq.com -p 25 -f 1605227279 -e caczsjchvyibi -q NIUYULING -r 1605227279@QQ.COM -n NIUYULING -s \"System ban IP\" -t \"%s\""
// 存储公网IP
char public_ip[BUFFER];
// 检测系统
int check_system()
{
if (0 == access("/etc/debian_version", F_OK)) {
return DEBISN_SYSTEM;
} else if (0 == access("/etc/centos-release", F_OK)) {
return CENTOS_SYSTEM;
}
return UNKNOWN_SYSTEM;
}
// 获取公网IP
char *get_public_ip(char *ip)
{
FILE *fp;
char buff[BUFFER];
memset(buff, 0, BUFFER);
if (NULL == (fp = popen("curl members.3322.org/dyndns/getip --silent", "r"))) {
perror("popen curl");
}
while (fgets(buff, BUFFER, fp) != NULL) {
buff[strlen(buff) - 1] = '\0';
}
if (NULL != fp)
pclose(fp);
return strcpy(ip, buff);
}
// 替换字符串
int strReplaceAll(char *str, char *sub, char *replace)
{
if (NULL == str || NULL == sub || NULL == replace) {
printf("strReplaceAll param error\n");
return 1;
}
char *p = NULL;
char *t = NULL;
char *q = NULL;
char *dst = NULL;
char *src = NULL;
int str_len = strlen(str);
int sub_len = strlen(sub);
int replace_len = strlen(replace);
p = str;
while ('\0' != *p) {
t = str + str_len;
q = strstr(str, sub);
if (NULL == q) /* 没有子串了,那么直接返回吧 */
break;
src = q + sub_len; /* 源头, 原有sub后的一个字符 */
dst = q + replace_len; /* 目的放完replace后的一个字符 */
memcpy(dst, src, t - src); /* 原有字符串后移,放出空间 */
memcpy(q, replace, replace_len); /* 将replace字符拷贝进来 */
str_len = str_len + replace_len - sub_len;
p = q + replace_len; /* p 下一轮replace后的一个字符 */
}
str[str_len] = '\0'; /* 通过'\0'表示结尾 */
return 0;
}
// 钉钉告警
int dingding_warning(char *illegal_ip, char *public_ip)
{
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl == NULL) {
return 1;
}
char jsonObj[BUFFER] = "{ \
\"msgtype\": \"text\", \
\"text\": { \
\"content\": \"Alert @PHONE 主机PUBLIC 非法主机IP被封禁 Warning!\" \
}, \
\"at\": { \
\"atMobiles\": [\"PHONE\"], \
\"isAtAll\": false \
} \
}";
strReplaceAll(jsonObj, "IP", illegal_ip);
strReplaceAll(jsonObj, "PHONE", PHONE);
strReplaceAll(jsonObj, "PUBLIC", public_ip);
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, DING_CURL);
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");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl_global_cleanup();
return res;
}
// 邮件告警
int mail_warning(char *illegal_ip, char *public_ip)
{
FILE *fp = NULL;
char buff[BUFFER];
char text[BUFFER] = "echo \"主机:HOST, 禁止IP访问!\" |";
memset(buff, 0, BUFFER);
strReplaceAll(text, "IP", illegal_ip);
strReplaceAll(text, "HOST", public_ip);
strcat(text, " mail -s \"System ban IP\" 1605227279@qq.com");
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 string[BUFFER+(sizeof(QQMAIL))];
char text[BUFFER] = "主机:HOST, 禁止IP访问!";
strReplaceAll(text, "IP", illegal_ip);
strReplaceAll(text, "HOST", public_ip);
memset(string, 0, BUFFER+(sizeof(QQMAIL)));
sprintf(string, QQMAIL, text);
system(string);
return 0;
}
// 封禁非法IP
int rule()
{
FILE *fp, *fc;
char p[2], splice_command[LONG_BUFFER], command[LONG_BUFFER], *temp, buffer[BUFFER], awk[BUFFER], iptables[BUFFER];
char p[2], splice_command[LONG_BUFFER], command[LONG_BUFFER], *temp, buffer[BUFFER], awk[BUFFER], iptables[BUFFER + (sizeof(IPTABLES))], iptables_check[BUFFER + (sizeof(IPTABLES))];
time_t timep;
struct tm *tp;
@ -26,19 +219,41 @@ int main(int argc, char *argv[], char **env)
memset(command, 0, LONG_BUFFER);
memset(buffer, 0, BUFFER);
memset(awk, 0, BUFFER);
memset(iptables, 0, BUFFER);
memset(iptables, 0, BUFFER+(sizeof(IPTABLES)));
memset(iptables_check, 0, BUFFER+(sizeof(IPTABLES)));
fp = NULL;
fc = NULL;
if (DEBISN_SYSTEM == check_system()) // Debian 系统规则
{
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;
}
while (fgets(buffer, BUFFER, fp) != NULL) {
temp = strstr(buffer, "rhost");
@ -48,7 +263,7 @@ int main(int argc, char *argv[], char **env)
strcat(splice_command, "\n");
}
}
printf("%s", splice_command); // 测试没问题
printf("%s", splice_command); // 打印所有非法IP
// 拼接命令
sprintf(awk, AWK, TOP_IP);
@ -56,24 +271,99 @@ int main(int argc, char *argv[], char **env)
strcat(command, splice_command);
strcat(command, "\"");
strcat(command, awk);
//printf("%s", command); // 测试没问题
if ((fp = popen(command, "r")) == NULL) { // 执行命令
perror("popen");
if ((fp = popen(command, "r")) == NULL) // 执行命令
{
perror("popen command");
return 1;
}
while (fgets(buffer, BUFFER, fp) != NULL) {
while (fgets(buffer, BUFFER, fp) != NULL) // 执行命令后, 为空时就不会
{
buffer[strlen(buffer) - 1] = '\0'; // 去除回车
sprintf(iptables, IPTABLES, buffer);
sprintf(iptables_check, IPTABLES_CHECK, buffer);
if (0 != system(iptables_check)) // 判断是否存在规则, 不存在时再添加规则
{
if (IS_DIND == 1) // 钉钉告警
{
dingding_warning(buffer, public_ip);
sleep(3);
}
if (IS_MAIL == 1) // 邮件告警
{
mail_warning(buffer, public_ip);
sleep(3);
}
if (IS_QQMAIL == 1) // 邮件告警
{
QQ_mail_warning(buffer, public_ip);
sleep(3);
}
if ((fc = popen(iptables, "r")) == NULL) {
perror("popen");
perror("popen iptables");
return 1;
}
}
}
if (fp != NULL)
pclose(fp);
if (fc != NULL)
pclose(fc);
return 0;
}
static void sig_child(int signo)
{
pid_t pid;
int stat;
// 处理僵尸进程
while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) ;
return;
}
int main(int argc, char *argv[], char **env)
{
memset(public_ip, 0, BUFFER);
get_public_ip(public_ip);
signal(SIGCHLD, sig_child); // 创建捕捉子进程退出信号
if (argv[1] != NULL && 0 == strcmp(argv[1], "-d"))
{
if (daemon(1, 1)) // 守护进程
{
perror("daemon");
return -1;
}
while (1) {
rule();
sleep(TIME);
}
}
else
{
rule();
}
return 0;
}

BIN
rhost.o

Binary file not shown.