增加告警、优化
This commit is contained in:
parent
86d7bf5780
commit
13d417727c
6
Makefile
6
Makefile
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
@ -42,6 +42,7 @@ function run()
|
||||
mail -s "System Log" ${email_address} < ${log_file}
|
||||
rm ${log_file}
|
||||
fi
|
||||
|
||||
sync
|
||||
}
|
||||
|
||||
|
342
rhost.c
342
rhost.c
@ -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,18 +219,40 @@ 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 (tp->tm_mday >= 10) {
|
||||
if ((fp = popen(GE_10, "r")) == NULL) {
|
||||
return 1;
|
||||
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 {
|
||||
if ((fp = popen(LE_10, "r")) == NULL) {
|
||||
return 1;
|
||||
}
|
||||
return UNKNOWN_SYSTEM;
|
||||
}
|
||||
|
||||
while (fgets(buffer, BUFFER, fp) != NULL) {
|
||||
@ -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) {
|
||||
buffer[strlen(buffer) - 1] = '\0'; // 去除回车
|
||||
|
||||
while (fgets(buffer, BUFFER, fp) != NULL) // 执行命令后, 为空时就不会
|
||||
{
|
||||
|
||||
buffer[strlen(buffer) - 1] = '\0'; // 去除回车
|
||||
sprintf(iptables, IPTABLES, buffer);
|
||||
if ((fc = popen(iptables, "r")) == NULL) {
|
||||
perror("popen");
|
||||
return 1;
|
||||
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 iptables");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pclose(fp);
|
||||
pclose(fc);
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user