denyhosts/rhost.c

367 lines
9.4 KiB
C
Raw Normal View History

2019-09-24 08:53:00 +08:00
2022-07-07 16:52:24 +08:00
#include "conf.h"
#include "rhost.h"
#include "libiptc.h"
2022-06-26 19:49:00 +08:00
// 存储公网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) {
2022-08-09 15:25:06 +08:00
printf("strReplaceAll\n");
2022-06-26 19:49:00 +08:00
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);
2022-08-09 15:25:06 +08:00
if (NULL == q) // 没有子串了直接返回
2022-06-26 19:49:00 +08:00
break;
2022-08-09 15:25:06 +08:00
src = q + sub_len; // 源头, 原有sub后的一个字符
dst = q + replace_len; // 目的放完replace后的一个字符
memcpy(dst, src, t - src); // 原有字符串后移,放出空间
memcpy(q, replace, replace_len); // 将replace字符拷贝进来
2022-06-26 19:49:00 +08:00
str_len = str_len + replace_len - sub_len;
2022-08-09 15:25:06 +08:00
p = q + replace_len; // p 下一轮replace后的一个字符
2022-06-26 19:49:00 +08:00
}
2022-08-09 15:25:06 +08:00
str[str_len] = '\0'; // 通过'\0'表示结尾
2022-06-26 19:49:00 +08:00
return 0;
}
// 钉钉告警
2022-07-07 16:52:24 +08:00
int dingding_warning(char *illegal_ip, char *public_ip, conf *conf)
2022-06-26 19:49:00 +08:00
{
2022-07-07 16:52:24 +08:00
FILE *fp;
if ((fp = fopen("libcurl_ding.log", "wt+")) == NULL){
return 1;
}
2022-06-26 19:49:00 +08:00
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);
2022-07-07 16:52:24 +08:00
strReplaceAll(jsonObj, "PHONE", conf->PHONE);
2022-06-26 19:49:00 +08:00
strReplaceAll(jsonObj, "PUBLIC", public_ip);
2022-07-07 16:52:24 +08:00
//printf("%s\n", jsonObj);
2022-06-26 19:49:00 +08:00
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");
2022-07-07 16:52:24 +08:00
curl_easy_setopt(curl, CURLOPT_URL, conf->DING_WEBHOOK);
2022-06-26 19:49:00 +08:00
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");
2022-07-07 16:52:24 +08:00
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
2022-06-26 19:49:00 +08:00
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl_global_cleanup();
2022-07-07 16:52:24 +08:00
fclose(fp);
2022-06-26 19:49:00 +08:00
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;
}
// 第三方邮箱告警
2022-07-07 16:52:24 +08:00
int QQ_mail_warning(char *illegal_ip, char *public_ip, conf *conf)
2022-06-26 19:49:00 +08:00
{
char string[BUFFER+(sizeof(QQMAIL))];
2022-07-07 16:52:24 +08:00
char text[BUFFER] = "主机:HOST, 禁止IP访问";
2022-06-26 19:49:00 +08:00
strReplaceAll(text, "IP", illegal_ip);
strReplaceAll(text, "HOST", public_ip);
memset(string, 0, BUFFER+(sizeof(QQMAIL)));
2022-07-07 16:52:24 +08:00
sprintf(string, QQMAIL, conf->SEND_QQ, conf->QQMAIL_KEY, conf->RECV_MAIL, text);
2022-06-26 19:49:00 +08:00
system(string);
return 0;
}
// 封禁非法IP
2022-07-07 16:52:24 +08:00
int rule(conf *conf)
2019-09-24 08:53:00 +08:00
{
2021-07-11 10:10:55 +08:00
FILE *fp, *fc;
2022-08-09 15:25:06 +08:00
//char p[2], splice_command[LONG_BUFFER], command[LONG_BUFFER], *temp, buffer[BUFFER], awk[BUFFER], iptables[BUFFER + (sizeof(IPTABLES))], iptables_check[BUFFER + (sizeof(IPTABLES_CHECK))];
char p[2], splice_command[LONG_BUFFER], command[LONG_BUFFER], *temp, buffer[BUFFER], awk[BUFFER];
2021-07-11 10:10:55 +08:00
2019-09-24 08:53:00 +08:00
time_t timep;
2021-07-11 10:10:55 +08:00
struct tm *tp;
2019-09-24 08:53:00 +08:00
time(&timep);
2021-07-11 10:10:55 +08:00
tp = localtime(&timep);
memset(splice_command, 0, LONG_BUFFER);
memset(command, 0, LONG_BUFFER);
memset(buffer, 0, BUFFER);
memset(awk, 0, BUFFER);
2022-08-09 15:25:06 +08:00
//memset(iptables, 0, BUFFER+(sizeof(IPTABLES)));
//memset(iptables_check, 0, BUFFER+(sizeof(IPTABLES_CHECK)));
2021-07-11 10:10:55 +08:00
fp = NULL;
fc = NULL;
2022-06-26 19:49:00 +08:00
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;
}
2019-09-24 08:53:00 +08:00
}
2022-06-26 19:49:00 +08:00
} 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;
}
2019-09-24 08:53:00 +08:00
}
2022-06-26 19:49:00 +08:00
} else {
return UNKNOWN_SYSTEM;
2019-09-24 08:53:00 +08:00
}
2022-06-26 19:49:00 +08:00
2019-09-24 08:53:00 +08:00
while (fgets(buffer, BUFFER, fp) != NULL) {
temp = strstr(buffer, "rhost");
sscanf(temp, "rhost=%s", temp);
2021-07-11 10:10:55 +08:00
if (atoi(strncpy(p, temp, 1)) > 0) {
strcat(splice_command, temp);
strcat(splice_command, "\n");
}
}
2022-07-07 16:52:24 +08:00
printf("%s", splice_command); // 打印所有非法IP
2022-06-26 19:49:00 +08:00
2021-07-11 10:10:55 +08:00
// 拼接命令
2022-07-07 16:52:24 +08:00
sprintf(awk, AWK, conf->REFUSE_NUMBER);
2021-07-11 10:10:55 +08:00
strcpy(command, "echo \"");
strcat(command, splice_command);
strcat(command, "\"");
strcat(command, awk);
2022-06-26 19:49:00 +08:00
2022-07-07 16:52:24 +08:00
if ((fp = popen(command, "r")) == NULL) // 执行命令
2022-06-26 19:49:00 +08:00
{
perror("popen command");
2021-07-11 10:10:55 +08:00
return 1;
}
2022-06-26 19:49:00 +08:00
2022-07-07 16:52:24 +08:00
while (fgets(buffer, BUFFER, fp) != NULL) // 执行命令后, 为空时就不会
2022-06-26 19:49:00 +08:00
{
2022-07-07 16:52:24 +08:00
buffer[strlen(buffer) - 1] = '\0'; // 去除回车
2022-08-09 15:25:06 +08:00
//sprintf(iptables, IPTABLES, buffer);
//sprintf(iptables_check, IPTABLES_CHECK, buffer);
2022-06-26 19:49:00 +08:00
2022-07-08 09:16:58 +08:00
//if (0 != system(iptables_check)) // 调用iptables命令判断是否存在规则, 不存在时再添加规则
if (0 != show_all_rule(buffer)) // libiptc库判断
2022-06-26 19:49:00 +08:00
{
2022-07-07 16:52:24 +08:00
if (conf->IS_DING_WEBHOOK == 1) // 钉钉告警
2022-06-26 19:49:00 +08:00
{
2022-07-07 16:52:24 +08:00
dingding_warning(buffer, public_ip, conf);
2022-06-26 19:49:00 +08:00
sleep(3);
}
2022-07-07 16:52:24 +08:00
if (conf->IS_MAIL == 1) // 邮件告警
2022-06-26 19:49:00 +08:00
{
mail_warning(buffer, public_ip);
sleep(3);
}
2022-07-07 16:52:24 +08:00
if (conf->IS_QQMAIL == 1) // 邮件告警
2022-06-26 19:49:00 +08:00
{
2022-07-07 16:52:24 +08:00
QQ_mail_warning(buffer, public_ip, conf);
2022-06-26 19:49:00 +08:00
sleep(3);
}
2022-07-07 16:52:24 +08:00
/*
2022-07-08 09:16:58 +08:00
// 调用命令下发规则
2022-06-26 19:49:00 +08:00
if ((fc = popen(iptables, "r")) == NULL) {
perror("popen iptables");
return 1;
}
2022-07-07 16:52:24 +08:00
*/
2022-07-13 11:27:22 +08:00
// libiptc 库插入规则 iptables -t filter -A INPUT -p tcp -s xxxx -j DROP
2022-07-07 16:52:24 +08:00
unsigned int destIp;
inet_pton(AF_INET, buffer, &destIp);
iptc_add_rule("filter", "INPUT", IPPROTO_TCP, NULL, NULL, 0, destIp, NULL, NULL, "DROP", NULL, 1);
2021-07-11 10:10:55 +08:00
}
2019-09-24 08:53:00 +08:00
}
2022-06-26 19:49:00 +08:00
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) ;
2021-07-11 10:10:55 +08:00
2022-06-26 19:49:00 +08:00
return;
}
int main(int argc, char *argv[], char **env)
{
2022-07-07 16:52:24 +08:00
conf *conf = (struct CONF *)malloc(sizeof(struct CONF));
read_conf("rhost.conf", conf);
//ptintf_conf(conf);
2022-06-26 19:49:00 +08:00
memset(public_ip, 0, BUFFER);
get_public_ip(public_ip);
signal(SIGCHLD, sig_child); // 创建捕捉子进程退出信号
2022-07-07 16:52:24 +08:00
if (0 == strcmp(conf->DAEMON, "on"))
{
goto goto_daemon;
}
2022-06-26 19:49:00 +08:00
if (argv[1] != NULL && 0 == strcmp(argv[1], "-d"))
{
2022-07-07 16:52:24 +08:00
goto_daemon:
2022-06-26 19:49:00 +08:00
if (daemon(1, 1)) // 守护进程
{
perror("daemon");
return -1;
}
while (1) {
2022-07-07 16:52:24 +08:00
rule(conf);
2022-06-26 19:49:00 +08:00
2022-07-07 16:52:24 +08:00
sleep(conf->TIME);
2022-06-26 19:49:00 +08:00
}
}
else
{
2022-07-07 16:52:24 +08:00
rule(conf);
2022-06-26 19:49:00 +08:00
}
2022-07-07 16:52:24 +08:00
free_conf(conf);
free(conf);
2019-09-24 08:53:00 +08:00
return 0;
}
2022-06-26 19:49:00 +08:00