使用libiptc下发规则
This commit is contained in:
parent
13d417727c
commit
bb544a72de
4
Makefile
4
Makefile
@ -1,10 +1,10 @@
|
|||||||
CROSS_COMPILE ?=
|
CROSS_COMPILE ?=
|
||||||
CC := $(CROSS_COMPILE)gcc
|
CC := $(CROSS_COMPILE)gcc
|
||||||
CFLAGS += -g -Wall
|
CFLAGS += -g -Wall
|
||||||
LIB += -lcurl
|
LIB += -lcurl -lip4tc
|
||||||
OBG = rhost
|
OBG = rhost
|
||||||
|
|
||||||
all: rhost.o
|
all: conf.o rhost.o libiptc.o
|
||||||
$(CC) $(CFLAGS) $^ -o $(OBG) $(LIB)
|
$(CC) $(CFLAGS) $^ -o $(OBG) $(LIB)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
232
conf.c
Normal file
232
conf.c
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
#include "conf.h"
|
||||||
|
|
||||||
|
int8_t copy_new_mem(char *src, int src_len, char **dest)
|
||||||
|
{
|
||||||
|
*dest = (char *)malloc(src_len + 1);
|
||||||
|
if (*dest == NULL)
|
||||||
|
return 1;
|
||||||
|
memcpy(*dest, src, src_len);
|
||||||
|
*((*dest) + src_len) = '\0';
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 在content中,设置变量(var)的首地址,值(val)的位置首地址和末地址,返回下一行指针 */
|
||||||
|
static char *set_var_val_lineEnd(char *content, char **var, char **val_begin, char **val_end)
|
||||||
|
{
|
||||||
|
|
||||||
|
char *p, *pn, *lineEnd;
|
||||||
|
;
|
||||||
|
int val_len;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (content == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (; *content == ' ' || *content == '\t' || *content == '\r' || *content == '\n'; content++) ;
|
||||||
|
if (*content == '\0')
|
||||||
|
return NULL;
|
||||||
|
*var = content;
|
||||||
|
pn = strchr(content, '\n');
|
||||||
|
p = strchr(content, '=');
|
||||||
|
if (p == NULL) {
|
||||||
|
if (pn) {
|
||||||
|
content = pn + 1;
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
content = p;
|
||||||
|
//将变量以\0结束
|
||||||
|
for (p--; *p == ' ' || *p == '\t'; p--) ;
|
||||||
|
*(p + 1) = '\0';
|
||||||
|
//值的首地址
|
||||||
|
for (content++; *content == ' ' || *content == '\t'; content++) ;
|
||||||
|
if (*content == '\0')
|
||||||
|
return NULL;
|
||||||
|
//双引号引起来的值支持换行
|
||||||
|
if (*content == '"') {
|
||||||
|
*val_begin = content + 1;
|
||||||
|
*val_end = strstr(*val_begin, "\";");
|
||||||
|
if (*val_end != NULL)
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
*val_begin = content;
|
||||||
|
*val_end = strchr(content, ';');
|
||||||
|
if (pn && *val_end > pn) {
|
||||||
|
content = pn + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*val_end) {
|
||||||
|
**val_end = '\0';
|
||||||
|
val_len = *val_end - *val_begin;
|
||||||
|
lineEnd = *val_end;
|
||||||
|
} else {
|
||||||
|
val_len = strlen(*val_begin);
|
||||||
|
*val_end = lineEnd = *val_begin + val_len;
|
||||||
|
}
|
||||||
|
*val_end = *val_begin + val_len;
|
||||||
|
//printf("var[%s]\nbegin[%s]\n\n", *var, *val_begin);
|
||||||
|
return lineEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_global_module(char *content, conf * conf)
|
||||||
|
{
|
||||||
|
char *var, *val_begin, *val_end, *lineEnd;
|
||||||
|
int val_begin_len;
|
||||||
|
|
||||||
|
while ((lineEnd = set_var_val_lineEnd(content, &var, &val_begin, &val_end)) != NULL) {
|
||||||
|
if (strcasecmp(var, "DAEMON") == 0) {
|
||||||
|
val_begin_len = val_end - val_begin;
|
||||||
|
|
||||||
|
if (copy_new_mem(val_begin, val_begin_len, &conf->DAEMON) != 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(var, "TIME") == 0) {
|
||||||
|
val_begin_len = val_end - val_begin;
|
||||||
|
conf->TIME = atoi(val_begin);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
val_begin_len = val_end - val_begin;
|
||||||
|
conf->IS_MAIL = atoi(val_begin);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(var, "IS_DING_WEBHOOK") == 0) {
|
||||||
|
val_begin_len = val_end - val_begin;
|
||||||
|
conf->IS_DING_WEBHOOK = atoi(val_begin);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(var, "PHONE") == 0) {
|
||||||
|
val_begin_len = val_end - val_begin;
|
||||||
|
if (copy_new_mem(val_begin, val_begin_len, &conf->PHONE) != 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(var, "DING_WEBHOOK") == 0) {
|
||||||
|
val_begin_len = val_end - val_begin;
|
||||||
|
if (copy_new_mem(val_begin, val_begin_len, &conf->DING_WEBHOOK) != 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcasecmp(var, "IS_QQMAIL") == 0) {
|
||||||
|
val_begin_len = val_end - 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) {
|
||||||
|
val_begin_len = val_end - val_begin;
|
||||||
|
if (copy_new_mem(val_begin, val_begin_len, &conf->RECV_MAIL) != 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
content = strchr(lineEnd + 1, '\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 在buff中读取模块(global http https httpdns httpudp)内容 */
|
||||||
|
static char *read_module(char *buff, const char *module_name)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char *p, *p0;
|
||||||
|
|
||||||
|
len = strlen(module_name);
|
||||||
|
p = buff;
|
||||||
|
while (1) {
|
||||||
|
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
|
||||||
|
p++;
|
||||||
|
if (strncasecmp(p, module_name, len) == 0) {
|
||||||
|
p += len;
|
||||||
|
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
|
||||||
|
p++;
|
||||||
|
if (*p == '{')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((p = strchr(p, '\n')) == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((p0 = strchr(++p, '}')) == NULL)
|
||||||
|
return NULL;
|
||||||
|
return strndup(p, p0 - p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_conf(char *filename, conf * configure)
|
||||||
|
{
|
||||||
|
char *buff, *global_content;
|
||||||
|
FILE *file;
|
||||||
|
long file_size;
|
||||||
|
int return_val;
|
||||||
|
|
||||||
|
file = fopen(filename, "r");
|
||||||
|
if (file == NULL)
|
||||||
|
perror("cannot open config file.");
|
||||||
|
fseek(file, 0, SEEK_END);
|
||||||
|
file_size = ftell(file);
|
||||||
|
buff = (char *)alloca(file_size + 1);
|
||||||
|
if (buff == NULL)
|
||||||
|
perror("out of memory.");
|
||||||
|
rewind(file);
|
||||||
|
if (1 > (return_val = fread(buff, file_size, 1, file)))
|
||||||
|
perror("fread");
|
||||||
|
fclose(file);
|
||||||
|
buff[file_size] = '\0';
|
||||||
|
|
||||||
|
if ((global_content = read_module(buff, "global")) == NULL) {
|
||||||
|
perror("read global module error");
|
||||||
|
}
|
||||||
|
parse_global_module(global_content, configure);
|
||||||
|
free(global_content);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_conf(conf * conf)
|
||||||
|
{
|
||||||
|
free(conf->DAEMON);
|
||||||
|
free(conf->PHONE);
|
||||||
|
free(conf->DING_WEBHOOK);
|
||||||
|
free(conf->SEND_QQ);
|
||||||
|
free(conf->QQMAIL_KEY);
|
||||||
|
free(conf->RECV_MAIL);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ptintf_conf(conf *conf)
|
||||||
|
{
|
||||||
|
printf("%s\n", conf->DAEMON);
|
||||||
|
printf("%d\n", conf->TIME);
|
||||||
|
printf("%d\n", conf->REFUSE_NUMBER);
|
||||||
|
printf("%d\n", conf->IS_MAIL);
|
||||||
|
printf("%d\n", conf->IS_DING_WEBHOOK);
|
||||||
|
printf("%s\n", conf->PHONE);
|
||||||
|
printf("%s\n", conf->DING_WEBHOOK);
|
||||||
|
printf("%d\n", conf->IS_QQMAIL);
|
||||||
|
printf("%s\n", conf->SEND_QQ);
|
||||||
|
printf("%s\n", conf->QQMAIL_KEY);
|
||||||
|
printf("%s\n", conf->RECV_MAIL);
|
||||||
|
}
|
32
conf.h
Normal file
32
conf.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef CONF_H
|
||||||
|
#define CONF_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct CONF {
|
||||||
|
char *DAEMON;
|
||||||
|
int TIME;
|
||||||
|
|
||||||
|
int REFUSE_NUMBER;
|
||||||
|
|
||||||
|
int IS_MAIL;
|
||||||
|
|
||||||
|
int IS_DING_WEBHOOK;
|
||||||
|
char *PHONE;
|
||||||
|
char *DING_WEBHOOK;
|
||||||
|
|
||||||
|
int IS_QQMAIL;
|
||||||
|
char *SEND_QQ;
|
||||||
|
char *QQMAIL_KEY;
|
||||||
|
char *RECV_MAIL;
|
||||||
|
} conf;
|
||||||
|
|
||||||
|
void read_conf(char *filename, conf *configure);
|
||||||
|
void free_conf(conf * conf);
|
||||||
|
void ptintf_conf(conf *conf);
|
||||||
|
|
||||||
|
#endif
|
49
denyhosts.sh
49
denyhosts.sh
@ -6,41 +6,46 @@
|
|||||||
# Time: 20170909
|
# Time: 20170909
|
||||||
#
|
#
|
||||||
|
|
||||||
|
source /etc/profile
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
send_mail=0;
|
SEND_MAIL=0
|
||||||
pwd_path="/root";
|
PWD_PATH="/root";
|
||||||
TIME=`date +"%Y%m%d%H%M"`;
|
TIME=`date +"%Y%m%d%H%M"`;
|
||||||
log_file="${pwd_path}/${TIME}.log";
|
LOG_FILE="${PWD_PATH}/${TIME}.log";
|
||||||
email_address="1605227279@qq.com";
|
EMAIL_ADDRESS="1605227279@qq.com";
|
||||||
|
IPTABLES=$(which iptables)
|
||||||
|
|
||||||
|
IPTABLES_SAVE=$(which iptables-save)
|
||||||
}
|
}
|
||||||
|
|
||||||
function run()
|
function run()
|
||||||
{
|
{
|
||||||
echo "Read-Only Memory,ROM:" &>> ${log_file}
|
echo "Read-Only Memory,ROM:" &>> ${LOG_FILE}
|
||||||
df -am &>> ${log_file}
|
df -am &>> ${LOG_FILE}
|
||||||
|
|
||||||
echo "random access memory,RAM:" &>> ${log_file}
|
echo "random access memory,RAM:" &>> ${LOG_FILE}
|
||||||
free -hl &>> ${log_file}
|
free -hl &>> ${LOG_FILE}
|
||||||
|
|
||||||
echo "System process:" &>> ${log_file}
|
echo "System process:" &>> ${LOG_FILE}
|
||||||
ps -axjf &>> ${log_file}
|
ps -axwwjf &>> ${LOG_FILE}
|
||||||
|
|
||||||
echo "Network Connections" &>> ${log_file}
|
echo "Network Connections" &>> ${LOG_FILE}
|
||||||
netstat -tnulp &>> ${log_file}
|
netstat -tnulp &>> ${LOG_FILE}
|
||||||
|
|
||||||
echo "System SSH authorization information:" &>> ${log_file}
|
echo "System SSH authorization information:" &>> ${LOG_FILE}
|
||||||
/root/denyhosts/rhost | awk '{a[$1]+=1;} END {for(i in a){print a[i]" "i;}}' &>> ${log_file}
|
/root/denyhosts/rhost | awk '{a[$1]+=1;} END {for(i in a){print a[i]" "i;}}' &>> ${LOG_FILE}
|
||||||
|
|
||||||
/sbin/iptables-save > /root/ipv4tables
|
$IPTABLES_SAVE > /root/ipv4tables
|
||||||
|
|
||||||
echo "" &>> ${log_file}
|
echo "" &>> ${LOG_FILE}
|
||||||
echo "Iptables filter table" &>> ${log_file}
|
echo "Iptables filter table" &>> ${LOG_FILE}
|
||||||
/sbin/iptables -L -n --line-numbers &>> ${log_file}
|
$IPTABLES -L -n --line-numbers &>> ${LOG_FILE}
|
||||||
echo "" &>> ${log_file}
|
echo "" &>> ${LOG_FILE}
|
||||||
|
|
||||||
if test $send_mail = 1; then
|
if test $SEND_MAIL = 1; then
|
||||||
mail -s "System Log" ${email_address} < ${log_file}
|
mail -s "System Log" ${EMAIL_ADDRESS} < ${LOG_FILE}
|
||||||
rm ${log_file}
|
rm ${LOG_FILE}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sync
|
sync
|
||||||
|
209
libiptc.c
Normal file
209
libiptc.c
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
#include "libiptc.h"
|
||||||
|
|
||||||
|
|
||||||
|
int x_get_rule(const char *chain, struct xtc_handle *handle, char *ipv4)
|
||||||
|
{
|
||||||
|
int r=1;
|
||||||
|
const struct ipt_entry *entry;
|
||||||
|
|
||||||
|
for (entry = iptc_first_rule(chain, handle); entry; entry = iptc_next_rule(entry, handle)) {
|
||||||
|
iptc_get_target(entry, handle);
|
||||||
|
|
||||||
|
char addr[33];
|
||||||
|
memset(addr, 0, 33);
|
||||||
|
inet_ntop(AF_INET, &(entry->ip.dst), addr, sizeof(addr));
|
||||||
|
printf("%s\n", addr);
|
||||||
|
if (0 == strcmp(ipv4, addr))
|
||||||
|
{
|
||||||
|
r=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int show_all_rule(char *ipv4)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
struct xtc_handle *handle;
|
||||||
|
const char *chain = NULL;
|
||||||
|
struct ipt_counters counter;
|
||||||
|
|
||||||
|
handle = iptc_init("filter");
|
||||||
|
|
||||||
|
for (chain = iptc_first_chain(handle); chain; chain = iptc_next_chain(handle))
|
||||||
|
{
|
||||||
|
if (chain != NULL && handle != NULL) {
|
||||||
|
iptc_get_policy(chain, &counter, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = x_get_rule(chain, handle, ipv4);
|
||||||
|
if (r==0){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u_int16_t parse_port(const char *port)
|
||||||
|
{
|
||||||
|
return atoi(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_ports(const char *portstring, u_int16_t * ports)
|
||||||
|
{
|
||||||
|
char *buffer;
|
||||||
|
char *cp;
|
||||||
|
|
||||||
|
buffer = strdup(portstring);
|
||||||
|
if ((cp = strchr(buffer, ':')) == NULL)
|
||||||
|
ports[0] = ports[1] = parse_port(buffer);
|
||||||
|
else {
|
||||||
|
*cp = '\0';
|
||||||
|
cp++;
|
||||||
|
|
||||||
|
ports[0] = buffer[0] ? parse_port(buffer) : 0;
|
||||||
|
ports[1] = cp[0] ? parse_port(cp) : 0xFFFF;
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ipt_entry_match *get_match(const char *sports, const char *dports, unsigned int *nfcache, char *protocol)
|
||||||
|
{
|
||||||
|
struct ipt_entry_match *match;
|
||||||
|
struct ipt_udp *udpinfo;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
size = IPT_ALIGN(sizeof(*match)) + IPT_ALIGN(sizeof(*udpinfo));
|
||||||
|
match = (struct ipt_entry_match *)calloc(1, size);
|
||||||
|
match->u.match_size = size;
|
||||||
|
strncpy(match->u.user.name, protocol, IPT_FUNCTION_MAXNAMELEN);
|
||||||
|
|
||||||
|
udpinfo = (struct ipt_udp *)match->data;
|
||||||
|
udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF;
|
||||||
|
//printf("sports=%s,dports=%s\n", sports, dports);
|
||||||
|
if (sports) {
|
||||||
|
*nfcache |= NFC_IP_SRC_PT;
|
||||||
|
parse_ports(sports, udpinfo->spts);
|
||||||
|
}
|
||||||
|
if (dports) {
|
||||||
|
*nfcache |= NFC_IP_DST_PT;
|
||||||
|
parse_ports(dports, udpinfo->dpts);
|
||||||
|
}
|
||||||
|
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
int iptc_add_rule(const char *table, const char *chain, int protocol, const char *iniface, const char *outiface, unsigned int src,
|
||||||
|
unsigned int dest, const char *srcports, const char *destports, const char *target, const char *dnat_to, const int append)
|
||||||
|
{
|
||||||
|
struct xtc_handle *handle;
|
||||||
|
struct ipt_entry *chain_entry;
|
||||||
|
struct ipt_entry_match *entry_match = NULL;
|
||||||
|
struct ipt_entry_target *entry_target;
|
||||||
|
ipt_chainlabel labelit;
|
||||||
|
long match_size;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
chain_entry = (struct ipt_entry *)calloc(1, sizeof(*chain_entry));
|
||||||
|
|
||||||
|
if (src != 0) {
|
||||||
|
chain_entry->ip.src.s_addr = src;
|
||||||
|
chain_entry->ip.smsk.s_addr = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
if (dest != 0) {
|
||||||
|
chain_entry->ip.dst.s_addr = dest;
|
||||||
|
chain_entry->ip.dmsk.s_addr = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iniface)
|
||||||
|
strncpy(chain_entry->ip.iniface, iniface, IFNAMSIZ);
|
||||||
|
if (outiface)
|
||||||
|
strncpy(chain_entry->ip.outiface, outiface, IFNAMSIZ);
|
||||||
|
|
||||||
|
chain_entry->ip.proto = protocol;
|
||||||
|
if (IPPROTO_UDP == protocol)
|
||||||
|
entry_match = get_match(srcports, destports, &chain_entry->nfcache, "udp");
|
||||||
|
if (IPPROTO_TCP == protocol)
|
||||||
|
entry_match = get_match(srcports, destports, &chain_entry->nfcache, "tcp");
|
||||||
|
|
||||||
|
if (strcmp(target, "") == 0 || strcmp(target, IPTC_LABEL_ACCEPT) == 0 || strcmp(target, IPTC_LABEL_DROP) == 0 || strcmp(target, IPTC_LABEL_QUEUE) == 0 || strcmp(target, IPTC_LABEL_RETURN) == 0) {
|
||||||
|
size_t size;
|
||||||
|
size = IPT_ALIGN(sizeof(struct ipt_entry_target)) + IPT_ALIGN(sizeof(int));
|
||||||
|
entry_target = (struct ipt_entry_target *)calloc(1, size);
|
||||||
|
entry_target->u.user.target_size = size;
|
||||||
|
strncpy(entry_target->u.user.name, target, IPT_FUNCTION_MAXNAMELEN);
|
||||||
|
}
|
||||||
|
if (entry_match) {
|
||||||
|
match_size = entry_match->u.match_size;
|
||||||
|
} else
|
||||||
|
match_size = 0;
|
||||||
|
|
||||||
|
struct ipt_entry *tmp_ipt = chain_entry;
|
||||||
|
chain_entry = (struct ipt_entry *)realloc(chain_entry, sizeof(*chain_entry) + match_size + entry_target->u.target_size);
|
||||||
|
if (chain_entry == NULL) {
|
||||||
|
free(tmp_ipt);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(chain_entry->elems + match_size, entry_target, entry_target->u.target_size);
|
||||||
|
chain_entry->target_offset = sizeof(*chain_entry) + match_size;
|
||||||
|
chain_entry->next_offset = sizeof(*chain_entry) + match_size + entry_target->u.target_size;
|
||||||
|
if (entry_match) {
|
||||||
|
memcpy(chain_entry->elems, entry_match, match_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle = iptc_init(table);
|
||||||
|
if (!handle) {
|
||||||
|
printf("libiptc error: Can't initialize table %s, %s\n", table, iptc_strerror(errno));
|
||||||
|
free(chain_entry);
|
||||||
|
free(entry_target);
|
||||||
|
if (entry_match)
|
||||||
|
free(entry_match);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(labelit, chain, sizeof(ipt_chainlabel));
|
||||||
|
//printf("Chain name:%s\n", chain);
|
||||||
|
result = iptc_is_chain(chain, handle);
|
||||||
|
if (!result) {
|
||||||
|
printf("libiptc error: Chain %s does not exist!\n", chain);
|
||||||
|
free(chain_entry);
|
||||||
|
free(entry_target);
|
||||||
|
if (entry_match)
|
||||||
|
free(entry_match);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (append)
|
||||||
|
result = iptc_append_entry(labelit, chain_entry, handle);
|
||||||
|
else
|
||||||
|
result = iptc_insert_entry(labelit, chain_entry, 0, handle);
|
||||||
|
if (!result) {
|
||||||
|
printf("libiptc error: Can't add, %s\n", iptc_strerror(errno));
|
||||||
|
free(chain_entry);
|
||||||
|
free(entry_target);
|
||||||
|
if (entry_match)
|
||||||
|
free(entry_match);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
result = iptc_commit(handle);
|
||||||
|
if (!result) {
|
||||||
|
printf("libiptc error: Commit error, %s\n", iptc_strerror(errno));
|
||||||
|
free(chain_entry);
|
||||||
|
free(entry_target);
|
||||||
|
if (entry_match)
|
||||||
|
free(entry_match);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (entry_match)
|
||||||
|
free(entry_match);
|
||||||
|
free(entry_target);
|
||||||
|
free(chain_entry);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
38
libiptc.h
Normal file
38
libiptc.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef LIBIPTC_H
|
||||||
|
#define LIBIPTC_H
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <linux/netfilter/x_tables.h>
|
||||||
|
#include <libiptc/libiptc.h>
|
||||||
|
|
||||||
|
/* Source port. */
|
||||||
|
#define NFC_IP_SRC_PT 0x0200
|
||||||
|
/* Dest port. */
|
||||||
|
#define NFC_IP_DST_PT 0x0400
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef IPT_MIN_ALIGN
|
||||||
|
#define IPT_MIN_ALIGN (__alignof__(struct ipt_entry))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define IPT_ALIGN(s) (((s) + ((IPT_MIN_ALIGN)-1)) & ~((IPT_MIN_ALIGN)-1))
|
||||||
|
|
||||||
|
#define IPTC_ENTRY_SIZE XT_ALIGN(sizeof(struct ipt_entry))
|
||||||
|
#define IPTC_MATCH_SIZE XT_ALIGN(sizeof(struct ipt_entry_match) + sizeof(struct ipt_udp))
|
||||||
|
#define IPTC_TARGET_SIZE XT_ALIGN(sizeof(struct ipt_entry_target))
|
||||||
|
#define IPTC_FULL_SIZE IPTC_ENTRY_SIZE + IPTC_MATCH_SIZE + IPTC_TARGET_SIZE
|
||||||
|
|
||||||
|
|
||||||
|
int show_all_rule(char *ipv4);
|
||||||
|
int iptc_add_rule(const char *table, const char *chain, int protocol, const char *iniface, const char *outiface, unsigned int src,
|
||||||
|
unsigned int dest, const char *srcports, const char *destports, const char *target, const char *dnat_to, const int append);
|
||||||
|
|
||||||
|
#endif
|
112
rhost.c
112
rhost.c
@ -1,40 +1,8 @@
|
|||||||
#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>
|
|
||||||
|
|
||||||
#define CENTOS_SYSTEM 1
|
#include "conf.h"
|
||||||
#define DEBISN_SYSTEM 2
|
#include "rhost.h"
|
||||||
#define UNKNOWN_SYSTEM 3
|
#include "libiptc.h"
|
||||||
|
|
||||||
#define BUFFER 1024
|
|
||||||
#define LONG_BUFFER 1024*100
|
|
||||||
#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"
|
|
||||||
|
|
||||||
#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
|
// 存储公网IP
|
||||||
char public_ip[BUFFER];
|
char public_ip[BUFFER];
|
||||||
@ -112,8 +80,14 @@ int strReplaceAll(char *str, char *sub, char *replace)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 钉钉告警
|
// 钉钉告警
|
||||||
int dingding_warning(char *illegal_ip, char *public_ip)
|
int dingding_warning(char *illegal_ip, char *public_ip, conf *conf)
|
||||||
{
|
{
|
||||||
|
FILE *fp;
|
||||||
|
if ((fp = fopen("libcurl_ding.log", "wt+")) == NULL){
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
CURL *curl;
|
CURL *curl;
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
|
|
||||||
@ -135,27 +109,29 @@ int dingding_warning(char *illegal_ip, char *public_ip)
|
|||||||
}";
|
}";
|
||||||
|
|
||||||
strReplaceAll(jsonObj, "IP", illegal_ip);
|
strReplaceAll(jsonObj, "IP", illegal_ip);
|
||||||
strReplaceAll(jsonObj, "PHONE", PHONE);
|
strReplaceAll(jsonObj, "PHONE", conf->PHONE);
|
||||||
strReplaceAll(jsonObj, "PUBLIC", public_ip);
|
strReplaceAll(jsonObj, "PUBLIC", public_ip);
|
||||||
printf("%s\n", jsonObj);
|
//printf("%s\n", jsonObj);
|
||||||
|
|
||||||
struct curl_slist *headers = NULL;
|
struct curl_slist *headers = NULL;
|
||||||
headers = curl_slist_append(headers, "Accept: application/json");
|
headers = curl_slist_append(headers, "Accept: application/json");
|
||||||
headers = curl_slist_append(headers, "Content-Type: application/json");
|
headers = curl_slist_append(headers, "Content-Type: application/json");
|
||||||
headers = curl_slist_append(headers, "charset: utf-8");
|
headers = curl_slist_append(headers, "charset: utf-8");
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, DING_CURL);
|
curl_easy_setopt(curl, CURLOPT_URL, conf->DING_WEBHOOK);
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||||
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonObj);
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonObj);
|
||||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl/0.1");
|
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl/0.1");
|
||||||
|
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
|
||||||
|
|
||||||
res = curl_easy_perform(curl);
|
res = curl_easy_perform(curl);
|
||||||
|
|
||||||
curl_easy_cleanup(curl);
|
curl_easy_cleanup(curl);
|
||||||
curl_global_cleanup();
|
curl_global_cleanup();
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -188,17 +164,18 @@ int mail_warning(char *illegal_ip, char *public_ip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 第三方邮箱告警
|
// 第三方邮箱告警
|
||||||
int QQ_mail_warning(char *illegal_ip, char *public_ip)
|
int QQ_mail_warning(char *illegal_ip, char *public_ip, conf *conf)
|
||||||
{
|
{
|
||||||
|
|
||||||
char string[BUFFER+(sizeof(QQMAIL))];
|
char string[BUFFER+(sizeof(QQMAIL))];
|
||||||
char text[BUFFER] = "主机:HOST, 禁止IP访问!";
|
char text[BUFFER] = "主机:HOST, 禁止IP访问";
|
||||||
|
|
||||||
strReplaceAll(text, "IP", illegal_ip);
|
strReplaceAll(text, "IP", illegal_ip);
|
||||||
strReplaceAll(text, "HOST", public_ip);
|
strReplaceAll(text, "HOST", public_ip);
|
||||||
|
|
||||||
memset(string, 0, BUFFER+(sizeof(QQMAIL)));
|
memset(string, 0, BUFFER+(sizeof(QQMAIL)));
|
||||||
sprintf(string, QQMAIL, text);
|
|
||||||
|
sprintf(string, QQMAIL, conf->SEND_QQ, conf->QQMAIL_KEY, conf->RECV_MAIL, text);
|
||||||
|
|
||||||
system(string);
|
system(string);
|
||||||
|
|
||||||
@ -206,10 +183,10 @@ int QQ_mail_warning(char *illegal_ip, char *public_ip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 封禁非法IP
|
// 封禁非法IP
|
||||||
int rule()
|
int rule(conf *conf)
|
||||||
{
|
{
|
||||||
FILE *fp, *fc;
|
FILE *fp, *fc;
|
||||||
char p[2], splice_command[LONG_BUFFER], command[LONG_BUFFER], *temp, buffer[BUFFER], awk[BUFFER], iptables[BUFFER + (sizeof(IPTABLES))], iptables_check[BUFFER + (sizeof(IPTABLES))];
|
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))];
|
||||||
|
|
||||||
time_t timep;
|
time_t timep;
|
||||||
struct tm *tp;
|
struct tm *tp;
|
||||||
@ -220,7 +197,7 @@ int rule()
|
|||||||
memset(buffer, 0, BUFFER);
|
memset(buffer, 0, BUFFER);
|
||||||
memset(awk, 0, BUFFER);
|
memset(awk, 0, BUFFER);
|
||||||
memset(iptables, 0, BUFFER+(sizeof(IPTABLES)));
|
memset(iptables, 0, BUFFER+(sizeof(IPTABLES)));
|
||||||
memset(iptables_check, 0, BUFFER+(sizeof(IPTABLES)));
|
memset(iptables_check, 0, BUFFER+(sizeof(IPTABLES_CHECK)));
|
||||||
fp = NULL;
|
fp = NULL;
|
||||||
fc = NULL;
|
fc = NULL;
|
||||||
|
|
||||||
@ -266,7 +243,7 @@ int rule()
|
|||||||
printf("%s", splice_command); // 打印所有非法IP
|
printf("%s", splice_command); // 打印所有非法IP
|
||||||
|
|
||||||
// 拼接命令
|
// 拼接命令
|
||||||
sprintf(awk, AWK, TOP_IP);
|
sprintf(awk, AWK, conf->REFUSE_NUMBER);
|
||||||
strcpy(command, "echo \"");
|
strcpy(command, "echo \"");
|
||||||
strcat(command, splice_command);
|
strcat(command, splice_command);
|
||||||
strcat(command, "\"");
|
strcat(command, "\"");
|
||||||
@ -286,31 +263,40 @@ int rule()
|
|||||||
sprintf(iptables, IPTABLES, buffer);
|
sprintf(iptables, IPTABLES, buffer);
|
||||||
sprintf(iptables_check, IPTABLES_CHECK, buffer);
|
sprintf(iptables_check, IPTABLES_CHECK, buffer);
|
||||||
|
|
||||||
|
//if (0 != system(iptables_check)) // 判断是否存在规则, 不存在时再添加规则
|
||||||
if (0 != system(iptables_check)) // 判断是否存在规则, 不存在时再添加规则
|
if (0 != show_all_rule(buffer))
|
||||||
{
|
{
|
||||||
if (IS_DIND == 1) // 钉钉告警
|
if (conf->IS_DING_WEBHOOK == 1) // 钉钉告警
|
||||||
{
|
{
|
||||||
dingding_warning(buffer, public_ip);
|
dingding_warning(buffer, public_ip, conf);
|
||||||
sleep(3);
|
sleep(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_MAIL == 1) // 邮件告警
|
if (conf->IS_MAIL == 1) // 邮件告警
|
||||||
{
|
{
|
||||||
mail_warning(buffer, public_ip);
|
mail_warning(buffer, public_ip);
|
||||||
sleep(3);
|
sleep(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_QQMAIL == 1) // 邮件告警
|
if (conf->IS_QQMAIL == 1) // 邮件告警
|
||||||
{
|
{
|
||||||
QQ_mail_warning(buffer, public_ip);
|
QQ_mail_warning(buffer, public_ip, conf);
|
||||||
sleep(3);
|
sleep(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if ((fc = popen(iptables, "r")) == NULL) {
|
if ((fc = popen(iptables, "r")) == NULL) {
|
||||||
perror("popen iptables");
|
perror("popen iptables");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// libiptc 库插入规则
|
||||||
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -336,16 +322,23 @@ static void sig_child(int signo)
|
|||||||
|
|
||||||
int main(int argc, char *argv[], char **env)
|
int main(int argc, char *argv[], char **env)
|
||||||
{
|
{
|
||||||
|
conf *conf = (struct CONF *)malloc(sizeof(struct CONF));
|
||||||
|
read_conf("rhost.conf", conf);
|
||||||
|
//ptintf_conf(conf);
|
||||||
|
|
||||||
memset(public_ip, 0, BUFFER);
|
memset(public_ip, 0, BUFFER);
|
||||||
get_public_ip(public_ip);
|
get_public_ip(public_ip);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
signal(SIGCHLD, sig_child); // 创建捕捉子进程退出信号
|
signal(SIGCHLD, sig_child); // 创建捕捉子进程退出信号
|
||||||
|
|
||||||
|
if (0 == strcmp(conf->DAEMON, "on"))
|
||||||
|
{
|
||||||
|
goto goto_daemon;
|
||||||
|
}
|
||||||
|
|
||||||
if (argv[1] != NULL && 0 == strcmp(argv[1], "-d"))
|
if (argv[1] != NULL && 0 == strcmp(argv[1], "-d"))
|
||||||
{
|
{
|
||||||
|
goto_daemon:
|
||||||
if (daemon(1, 1)) // 守护进程
|
if (daemon(1, 1)) // 守护进程
|
||||||
{
|
{
|
||||||
perror("daemon");
|
perror("daemon");
|
||||||
@ -353,17 +346,20 @@ int main(int argc, char *argv[], char **env)
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
rule();
|
rule(conf);
|
||||||
|
|
||||||
sleep(TIME);
|
sleep(conf->TIME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rule();
|
rule(conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
free_conf(conf);
|
||||||
|
free(conf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
rhost.conf
Normal file
17
rhost.conf
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
global {
|
||||||
|
DAEMON = "off"; // on开启后台运行,off不开启
|
||||||
|
TIME = "60"; // 睡眠时间
|
||||||
|
|
||||||
|
REFUSE_NUMBER = 5; // 拒绝攻击次数
|
||||||
|
|
||||||
|
IS_MAIL = 0; // 开启邮件告警
|
||||||
|
|
||||||
|
IS_DING_WEBHOOK = 1; // 开启叮叮告警
|
||||||
|
PHONE = "15565979082"; // @的人手机号
|
||||||
|
DING_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=7f069c672cb878987aa6772cca336740eece4ce36bde12b51b45e9f440e0565a"; // 钉钉WEBHOOK
|
||||||
|
|
||||||
|
IS_QQMAIL = 0; // 开启QQ邮箱告警
|
||||||
|
SEND_QQ = "1605227279"; // 发送者QQ
|
||||||
|
QQMAIL_KEY = "caczsjchvyibiabe"; // 发送者QQ密钥
|
||||||
|
RECV_MAIL = "1605227279"; // 接收者QQ
|
||||||
|
}
|
42
rhost.h
Normal file
42
rhost.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ifndef RHOST_H
|
||||||
|
#define RHOST_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>
|
||||||
|
|
||||||
|
|
||||||
|
#define CENTOS_SYSTEM 1
|
||||||
|
#define DEBISN_SYSTEM 2
|
||||||
|
#define UNKNOWN_SYSTEM 3
|
||||||
|
|
||||||
|
#define BUFFER 1024
|
||||||
|
#define LONG_BUFFER 1024*100
|
||||||
|
|
||||||
|
#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"
|
||||||
|
|
||||||
|
#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 "`which iptables` -t filter -I INPUT -s %s -j DROP"
|
||||||
|
#define IPTABLES_CHECK "`which iptables` -t filter -C INPUT -s %s -j DROP 2> /dev/null"
|
||||||
|
|
||||||
|
#define QQMAIL "qqMail -l smtp.qq.com -p 25 -f %s -e %s -q NIUYULING -r %s@QQ.COM -n NIUYULING -s \"System ban IP\" -t \"%s\""
|
||||||
|
|
||||||
|
|
||||||
|
extern void read_conf(char *filename, conf *configure);
|
||||||
|
extern void free_conf(conf * conf);
|
||||||
|
extern void ptintf_conf(conf *conf);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user