Get host error, kill process error.
This commit is contained in:
parent
8a44d18f0e
commit
d0564e6f31
@ -1,6 +1,6 @@
|
|||||||
[server]
|
[server]
|
||||||
uid=3004;
|
uid=3004;
|
||||||
process=2;
|
process=3;
|
||||||
timer=60;
|
timer=60;
|
||||||
local_port=9606;
|
local_port=9606;
|
||||||
pid_file=CProxy.pid;
|
pid_file=CProxy.pid;
|
||||||
@ -10,13 +10,11 @@ http_ip=192.168.1.102;
|
|||||||
http_port=1080;
|
http_port=1080;
|
||||||
http_del="x-online-host,X-Online-Host,host,Host";
|
http_del="x-online-host,X-Online-Host,host,Host";
|
||||||
http_first="[M] [U] [V]\r\nHost: [host]\r\n";
|
http_first="[M] [U] [V]\r\nHost: [host]\r\n";
|
||||||
;strrep = "Windows NT 10.0; Win64; x64->Linux";
|
|
||||||
;regrep = "Host*.+?->Host: iread.wo.cn:443";
|
|
||||||
|
|
||||||
[https]
|
[https]
|
||||||
https_ip=192.168.1.102;
|
https_ip=192.168.1.102;
|
||||||
https_port=1080;
|
https_port=1080;
|
||||||
https_del="Host,host";
|
https_del="Host,host";
|
||||||
https_first="[M] [U]?aixiao.me [V]\r\nHost: [U]\r\n";
|
https_first="[M] [H] [V]\r\nHost: [host]\r\n";
|
||||||
;strrep = "Windows NT 10.0; Win64; x64->Linux";
|
;strrep = "Windows NT 10.0; Win64; x64->Linux";
|
||||||
;regrep = "Host*.+?->Host: hu60.cn:443";
|
;regrep = "Host*.+?->Host: hu60.cn:443";
|
||||||
|
2
Makefile
2
Makefile
@ -5,7 +5,7 @@ CFLAGS += -g -O2 -Wall -I../iniparser/src -L../iniparser
|
|||||||
LIBS = -liniparser -pthread -static
|
LIBS = -liniparser -pthread -static
|
||||||
OBJ := CProxy
|
OBJ := CProxy
|
||||||
|
|
||||||
all: proxy.o http.o request.o picohttpparser.o conf.o timeout.o help.o
|
all: proxy.o http.o request.o picohttpparser.o conf.o timeout.o kill.o help.o
|
||||||
$(CC) $(CFLAGS) -o $(OBJ) $^ $(LIBS)
|
$(CC) $(CFLAGS) -o $(OBJ) $^ $(LIBS)
|
||||||
.c.o:
|
.c.o:
|
||||||
$(CC) $(CFLAGS) -c $< $(LIBS)
|
$(CC) $(CFLAGS) -c $< $(LIBS)
|
||||||
|
489
kill.c
Normal file
489
kill.c
Normal file
@ -0,0 +1,489 @@
|
|||||||
|
#include "kill.h"
|
||||||
|
|
||||||
|
static pid_t opt_ns_pid = 0;
|
||||||
|
|
||||||
|
static int exact = 1, reg = 0, wait_until_dead = 1, process_group =
|
||||||
|
0, ignore_case = 0;
|
||||||
|
static long younger_than = 0, older_than = 0;
|
||||||
|
|
||||||
|
typedef struct NAMEINFO {
|
||||||
|
const char *name;
|
||||||
|
int name_length;
|
||||||
|
struct stat st;
|
||||||
|
} NAMEINFO;
|
||||||
|
|
||||||
|
static double uptime()
|
||||||
|
{
|
||||||
|
char *savelocale;
|
||||||
|
char buf[2048];
|
||||||
|
FILE *file;
|
||||||
|
if (!(file = fopen(PROC_BASE "/uptime", "r"))) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
savelocale = setlocale(LC_NUMERIC, "C");
|
||||||
|
if (fscanf(file, "%2047s", buf) == EOF)
|
||||||
|
perror("uptime");
|
||||||
|
fclose(file);
|
||||||
|
setlocale(LC_NUMERIC, savelocale);
|
||||||
|
return atof(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static double process_age(const unsigned long long jf)
|
||||||
|
{
|
||||||
|
double age;
|
||||||
|
double sc_clk_tck = sysconf(_SC_CLK_TCK);
|
||||||
|
assert(sc_clk_tck > 0);
|
||||||
|
age = uptime() - jf / sc_clk_tck;
|
||||||
|
if (age < 0L)
|
||||||
|
return 0L;
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ns_type {
|
||||||
|
IPCNS = 0,
|
||||||
|
MNTNS,
|
||||||
|
NETNS,
|
||||||
|
PIDNS,
|
||||||
|
USERNS,
|
||||||
|
UTSNS
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *ns_names[] = {
|
||||||
|
[IPCNS] = "ipc",
|
||||||
|
[MNTNS] = "mnt",
|
||||||
|
[NETNS] = "net",
|
||||||
|
[PIDNS] = "pid",
|
||||||
|
[USERNS] = "user",
|
||||||
|
[UTSNS] = "uts",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *get_ns_name(int id)
|
||||||
|
{
|
||||||
|
if (id >= 6)
|
||||||
|
return NULL;
|
||||||
|
return ns_names[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_ns(pid_t pid, int id)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
char buff[50];
|
||||||
|
snprintf(buff, sizeof(buff), "/proc/%i/ns/%s", pid, get_ns_name(id));
|
||||||
|
if (stat(buff, &st))
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return st.st_ino;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int match_process_uid(pid_t pid, uid_t uid)
|
||||||
|
{
|
||||||
|
char buf[128];
|
||||||
|
uid_t puid;
|
||||||
|
FILE *f;
|
||||||
|
int re = -1;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof buf, PROC_BASE "/%d/status", pid);
|
||||||
|
if (!(f = fopen(buf, "r")))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (fgets(buf, sizeof buf, f)) {
|
||||||
|
if (sscanf(buf, "Uid:\t%d", &puid)) {
|
||||||
|
re = uid == puid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
if (re == -1) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return re;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_regexp_list(regex_t * reglist, int names)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < names; i++)
|
||||||
|
regfree(®list[i]);
|
||||||
|
free(reglist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static regex_t *build_regexp_list(int names, char **namelist)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
regex_t *reglist;
|
||||||
|
int flag = REG_EXTENDED | REG_NOSUB;
|
||||||
|
|
||||||
|
if (!(reglist = malloc(sizeof(regex_t) * names))) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ignore_case)
|
||||||
|
flag |= REG_ICASE;
|
||||||
|
|
||||||
|
for (i = 0; i < names; i++) {
|
||||||
|
if (regcomp(®list[i], namelist[i], flag) != 0) {
|
||||||
|
free_regexp_list(reglist, i);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reglist;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NAMEINFO *build_nameinfo(const int names, char **namelist)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
NAMEINFO *ni = NULL;
|
||||||
|
if ((ni = malloc(sizeof(NAMEINFO) * names)) == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < names; i++) {
|
||||||
|
ni[i].name = namelist[i];
|
||||||
|
ni[i].st.st_dev = 0;
|
||||||
|
if (!strchr(namelist[i], '/')) {
|
||||||
|
ni[i].name_length = strlen(namelist[i]);
|
||||||
|
} else if (stat(namelist[i], &(ni[i].st)) < 0) {
|
||||||
|
perror(namelist[i]);
|
||||||
|
free(ni);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ni;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
load_process_name_and_age(char *comm, double *process_age_sec,
|
||||||
|
const pid_t pid, int load_age)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
char *path;
|
||||||
|
char buf[1024];
|
||||||
|
char *startcomm, *endcomm;
|
||||||
|
unsigned lencomm;
|
||||||
|
*process_age_sec = 0;
|
||||||
|
|
||||||
|
if (asprintf(&path, PROC_BASE "/%d/stat", pid) < 0)
|
||||||
|
return -1;
|
||||||
|
if (!(file = fopen(path, "r"))) {
|
||||||
|
free(path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
if (fgets(buf, 1024, file) == NULL) {
|
||||||
|
fclose(file);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
startcomm = strchr(buf, '(') + 1;
|
||||||
|
endcomm = strrchr(startcomm, ')');
|
||||||
|
lencomm = endcomm - startcomm;
|
||||||
|
if (lencomm < 0)
|
||||||
|
lencomm = 0;
|
||||||
|
if (lencomm > COMM_LEN - 1)
|
||||||
|
lencomm = COMM_LEN - 1;
|
||||||
|
strncpy(comm, startcomm, lencomm);
|
||||||
|
comm[lencomm] = '\0';
|
||||||
|
|
||||||
|
endcomm += 2; // skip ") "
|
||||||
|
if (load_age) {
|
||||||
|
unsigned long long proc_stt_jf = 0;
|
||||||
|
if (sscanf
|
||||||
|
(endcomm,
|
||||||
|
"%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %Lu",
|
||||||
|
&proc_stt_jf) != 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*process_age_sec = process_age(proc_stt_jf);
|
||||||
|
}
|
||||||
|
return lencomm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
load_proc_cmdline(const pid_t pid, const char *comm, char **command,
|
||||||
|
int *got_long)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
char *path, *p, *command_buf;
|
||||||
|
int cmd_size = 128;
|
||||||
|
int okay;
|
||||||
|
|
||||||
|
if (asprintf(&path, PROC_BASE "/%d/cmdline", pid) < 0)
|
||||||
|
return -1;
|
||||||
|
if (!(file = fopen(path, "r"))) {
|
||||||
|
free(path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
|
||||||
|
if ((command_buf = (char *)malloc(cmd_size)) == NULL)
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
for (p = command_buf;; p++) {
|
||||||
|
int c;
|
||||||
|
if (p == (command_buf + cmd_size)) {
|
||||||
|
char *new_command_buf;
|
||||||
|
int cur_size = cmd_size;
|
||||||
|
cmd_size *= 2;
|
||||||
|
new_command_buf = (char *)realloc(command_buf, cmd_size);
|
||||||
|
if (!new_command_buf) {
|
||||||
|
if (command_buf)
|
||||||
|
free(command_buf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
command_buf = new_command_buf;
|
||||||
|
p = command_buf + cur_size;
|
||||||
|
}
|
||||||
|
c = fgetc(file);
|
||||||
|
if (c == EOF || c == '\0') {
|
||||||
|
*p = '\0';
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
*p = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (strlen(command_buf) == 0) {
|
||||||
|
okay = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p = strrchr(command_buf, '/');
|
||||||
|
p = p ? p + 1 : command_buf;
|
||||||
|
if (strncmp(p, comm, COMM_LEN - 1) == 0) {
|
||||||
|
okay = 1;
|
||||||
|
if (!(*command = strdup(p))) {
|
||||||
|
free(command_buf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void)fclose(file);
|
||||||
|
free(command_buf);
|
||||||
|
command_buf = NULL;
|
||||||
|
|
||||||
|
if (exact && !okay) {
|
||||||
|
*got_long = okay;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*got_long = okay;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static pid_t *create_pid_table(int *max_pids, int *pids)
|
||||||
|
{
|
||||||
|
pid_t self, *pid_table;
|
||||||
|
int pid;
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent *de;
|
||||||
|
|
||||||
|
self = getpid();
|
||||||
|
if (!(dir = opendir(PROC_BASE))) {
|
||||||
|
perror(PROC_BASE);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
*max_pids = 256;
|
||||||
|
pid_table = malloc(*max_pids * sizeof(pid_t));
|
||||||
|
if (!pid_table) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
*pids = 0;
|
||||||
|
while ((de = readdir(dir)) != NULL) {
|
||||||
|
if (!(pid = (pid_t) atoi(de->d_name)) || pid == self)
|
||||||
|
continue;
|
||||||
|
if (*pids == *max_pids) {
|
||||||
|
if (!(pid_table = realloc(pid_table, 2 * *pids * sizeof(pid_t)))) {
|
||||||
|
perror("realloc");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
*max_pids *= 2;
|
||||||
|
}
|
||||||
|
pid_table[(*pids)++] = pid;
|
||||||
|
}
|
||||||
|
(void)closedir(dir);
|
||||||
|
return pid_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define strcmp2(A,B,I) (I? strcasecmp((A),(B)):strcmp((A),(B)))
|
||||||
|
#define strncmp2(A,B,L,I) (I? strncasecmp((A),(B),(L)):strncmp((A),(B),(L)))
|
||||||
|
static int match_process_name(const char *proc_comm,
|
||||||
|
const int comm_len,
|
||||||
|
const char *proc_cmdline,
|
||||||
|
const char *match_name,
|
||||||
|
const int match_len, const int got_long)
|
||||||
|
{
|
||||||
|
if (comm_len == OLD_COMM_LEN - 1 && match_len >= OLD_COMM_LEN - 1) {
|
||||||
|
if (got_long) {
|
||||||
|
return (0 == strncmp2(match_name, proc_cmdline, OLD_COMM_LEN - 1,
|
||||||
|
ignore_case));
|
||||||
|
} else {
|
||||||
|
return (0 == strncmp2(match_name, proc_comm, OLD_COMM_LEN - 1,
|
||||||
|
ignore_case));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comm_len == COMM_LEN - 1 && match_len >= COMM_LEN - 1) {
|
||||||
|
if (got_long) {
|
||||||
|
return (0 == strncmp2(match_name, proc_cmdline, COMM_LEN - 1,
|
||||||
|
ignore_case));
|
||||||
|
} else {
|
||||||
|
return (0 == strncmp2(match_name, proc_comm, COMM_LEN - 1,
|
||||||
|
ignore_case));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (got_long) {
|
||||||
|
return (0 == strcmp2(match_name, proc_cmdline, ignore_case));
|
||||||
|
}
|
||||||
|
return (0 == strcmp2(match_name, proc_comm, ignore_case));
|
||||||
|
}
|
||||||
|
|
||||||
|
int kill_all(int signal, int name_count, char **namelist, struct passwd *pwent)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
NAMEINFO *name_info = NULL;
|
||||||
|
char *path, comm[COMM_LEN];
|
||||||
|
char *command = NULL;
|
||||||
|
pid_t *pid_table, *pid_killed;
|
||||||
|
pid_t *pgids = NULL;
|
||||||
|
int i, j, length, got_long, error;
|
||||||
|
int pids, max_pids, pids_killed;
|
||||||
|
unsigned long found;
|
||||||
|
regex_t *reglist = NULL;
|
||||||
|
long ns_ino = 0;
|
||||||
|
|
||||||
|
if (opt_ns_pid)
|
||||||
|
ns_ino = get_ns(opt_ns_pid, PIDNS);
|
||||||
|
|
||||||
|
if (name_count && reg)
|
||||||
|
reglist = build_regexp_list(name_count, namelist);
|
||||||
|
else if ((name_info = build_nameinfo(name_count, namelist)) == NULL)
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
pid_table = create_pid_table(&max_pids, &pids);
|
||||||
|
found = 0;
|
||||||
|
pids_killed = 0;
|
||||||
|
pid_killed = malloc(max_pids * sizeof(pid_t));
|
||||||
|
if (!pid_killed) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (process_group) {
|
||||||
|
pgids = calloc(pids, sizeof(pid_t));
|
||||||
|
if (!pgids) {
|
||||||
|
perror("malloc");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
got_long = 0;
|
||||||
|
for (i = 0; i < pids; i++) {
|
||||||
|
pid_t id;
|
||||||
|
int found_name = -1;
|
||||||
|
double process_age_sec = 0;
|
||||||
|
if (pwent && match_process_uid(pid_table[i], pwent->pw_uid) == 0)
|
||||||
|
continue;
|
||||||
|
if (opt_ns_pid && ns_ino && ns_ino != get_ns(pid_table[i], PIDNS))
|
||||||
|
continue;
|
||||||
|
length =
|
||||||
|
load_process_name_and_age(comm, &process_age_sec, pid_table[i],
|
||||||
|
(younger_than || older_than));
|
||||||
|
if (length < 0)
|
||||||
|
continue;
|
||||||
|
if (younger_than && (process_age_sec > younger_than))
|
||||||
|
continue;
|
||||||
|
if (older_than && (process_age_sec < older_than))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
got_long = 0;
|
||||||
|
if (command) {
|
||||||
|
free(command);
|
||||||
|
command = NULL;
|
||||||
|
}
|
||||||
|
if (length == COMM_LEN - 1)
|
||||||
|
if (load_proc_cmdline(pid_table[i], comm, &command, &got_long) < 0)
|
||||||
|
continue;
|
||||||
|
for (j = 0; j < name_count; j++) {
|
||||||
|
if (reg) {
|
||||||
|
if (regexec(®list[j], got_long ? command : comm, 0, NULL, 0)
|
||||||
|
!= 0)
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (!name_info[j].st.st_dev) {
|
||||||
|
if (!match_process_name(comm, length, command, namelist[j],
|
||||||
|
name_info[j].name_length, got_long))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
int ok = 1;
|
||||||
|
if (asprintf(&path, PROC_BASE "/%d/exe", pid_table[i]) < 0)
|
||||||
|
continue;
|
||||||
|
if (stat(path, &st) < 0)
|
||||||
|
ok = 0;
|
||||||
|
else if (name_info[j].st.st_dev != st.st_dev ||
|
||||||
|
name_info[j].st.st_ino != st.st_ino) {
|
||||||
|
size_t len = strlen(namelist[j]);
|
||||||
|
char *linkbuf = malloc(len + 1);
|
||||||
|
|
||||||
|
if (!linkbuf ||
|
||||||
|
readlink(path, linkbuf, len + 1) != (ssize_t) len ||
|
||||||
|
memcmp(namelist[j], linkbuf, len))
|
||||||
|
ok = 0;
|
||||||
|
free(linkbuf);
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
if (!ok)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
found_name = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (name_count && found_name == -1)
|
||||||
|
continue;
|
||||||
|
if (!process_group)
|
||||||
|
id = pid_table[i];
|
||||||
|
else {
|
||||||
|
int j;
|
||||||
|
|
||||||
|
id = getpgid(pid_table[i]);
|
||||||
|
pgids[i] = id;
|
||||||
|
for (j = 0; j < i; j++)
|
||||||
|
if (pgids[j] == id)
|
||||||
|
break;
|
||||||
|
if (j < i)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kill(process_group ? -id : id, signal) >= 0) {
|
||||||
|
if (found_name >= 0)
|
||||||
|
found |= 1UL << found_name;
|
||||||
|
pid_killed[pids_killed++] = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (command)
|
||||||
|
free(command);
|
||||||
|
if (reglist)
|
||||||
|
free_regexp_list(reglist, name_count);
|
||||||
|
free(pgids);
|
||||||
|
if (name_count)
|
||||||
|
error =
|
||||||
|
found ==
|
||||||
|
((1UL << (name_count - 1)) | ((1UL << (name_count - 1)) - 1)) ? 0 :
|
||||||
|
1;
|
||||||
|
else
|
||||||
|
error = pids_killed ? 0 : 1;
|
||||||
|
while (pids_killed && wait_until_dead) {
|
||||||
|
for (i = 0; i < pids_killed;) {
|
||||||
|
if (kill(process_group ? -pid_killed[i] : pid_killed[i], 0) < 0 &&
|
||||||
|
errno == ESRCH) {
|
||||||
|
pid_killed[i] = pid_killed[--pids_killed];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
//sleep(1);
|
||||||
|
}
|
||||||
|
free(pid_killed);
|
||||||
|
free(pid_table);
|
||||||
|
free(name_info);
|
||||||
|
return error;
|
||||||
|
}
|
60
kill.h
Normal file
60
kill.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#ifndef KILL_H
|
||||||
|
#define KILL_H
|
||||||
|
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <regex.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <locale.h>
|
||||||
|
|
||||||
|
#define COMM_LEN 64
|
||||||
|
#define OLD_COMM_LEN 16
|
||||||
|
#define _(String) (String)
|
||||||
|
#define rpmatch(line) \
|
||||||
|
( (line == NULL)? -1 : \
|
||||||
|
(*line == 'y' || *line == 'Y')? 1 : \
|
||||||
|
(*line == 'n' || *line == 'N')? 0 : \
|
||||||
|
-1 )
|
||||||
|
|
||||||
|
#define PROC_BASE "/proc"
|
||||||
|
#define MAX_NAMES (int)(sizeof(unsigned long)*8)
|
||||||
|
|
||||||
|
#define TSECOND "s"
|
||||||
|
#define TMINUTE "m"
|
||||||
|
#define THOUR "h"
|
||||||
|
#define TDAY "d"
|
||||||
|
#define TWEEK "w"
|
||||||
|
#define TMONTH "M"
|
||||||
|
#define TYEAR "y"
|
||||||
|
|
||||||
|
#define TMAX_SECOND 31536000
|
||||||
|
#define TMAX_MINUTE 525600
|
||||||
|
#define TMAX_HOUR 8760
|
||||||
|
#define TMAX_DAY 365
|
||||||
|
#define TMAX_WEEK 48
|
||||||
|
#define TMAX_MONTH 12
|
||||||
|
#define TMAX_YEAR 1
|
||||||
|
|
||||||
|
#define ER_REGFAIL -1
|
||||||
|
#define ER_NOMEM -2
|
||||||
|
#define ER_UNKWN -3
|
||||||
|
#define ER_OOFRA -4
|
||||||
|
|
||||||
|
int kill_all(int signal, int name_count, char **namelist, struct passwd *pwent);
|
||||||
|
|
||||||
|
#endif
|
23
proxy.c
23
proxy.c
@ -3,6 +3,7 @@
|
|||||||
#include "request.h"
|
#include "request.h"
|
||||||
#include "timeout.h"
|
#include "timeout.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
#include "kill.h"
|
||||||
#include "help.h"
|
#include "help.h"
|
||||||
|
|
||||||
#define SERVER_STOP 1
|
#define SERVER_STOP 1
|
||||||
@ -154,8 +155,12 @@ process_signal(int signal, char *process_name)
|
|||||||
for (; n >= 0; n--) {
|
for (; n >= 0; n--) {
|
||||||
if (signal == SERVER_STATUS)
|
if (signal == SERVER_STATUS)
|
||||||
printf("\t%d\n", num[n]);
|
printf("\t%d\n", num[n]);
|
||||||
if (signal == SERVER_STOP || signal == SERVER_RELOAD)
|
}
|
||||||
kill(num[n], SIGTERM);
|
if (signal == SERVER_STOP || signal == SERVER_RELOAD) {
|
||||||
|
//kill(num[n], SIGTERM);
|
||||||
|
struct passwd *pwent = NULL;
|
||||||
|
pwent = getpwnam("root");
|
||||||
|
return kill_all(15, 1, &process_name, pwent);
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
return 0;
|
return 0;
|
||||||
@ -263,8 +268,13 @@ int _main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (daemon(1, 1)) {
|
||||||
|
perror("daemon");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
while (process-- > 0 && fork() == 0)
|
while (process-- > 0 && fork() == 0)
|
||||||
|
|
||||||
epollfd = epoll_create(MAX_CONNECTION);
|
epollfd = epoll_create(MAX_CONNECTION);
|
||||||
if (epollfd == -1) {
|
if (epollfd == -1) {
|
||||||
perror("epoll_create");
|
perror("epoll_create");
|
||||||
@ -276,12 +286,7 @@ int _main(int argc, char *argv[])
|
|||||||
if (-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, server_sock, &event)) {
|
if (-1 == epoll_ctl(epollfd, EPOLL_CTL_ADD, server_sock, &event)) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daemon(1, 1)) {
|
|
||||||
perror("daemon");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setegid(configure->uid) == -1 || seteuid(configure->uid) == -1) // 设置uid
|
if (setegid(configure->uid) == -1 || seteuid(configure->uid) == -1) // 设置uid
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
|
44
request.c
44
request.c
@ -123,7 +123,7 @@ static char *regrep(char *str, int *str_len, const char *src, char *dest,
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除字符串head中第一位到character处并拼接string, character为空返回原字符串.(string字符替换第一个字符到character处)
|
// 删除字符串head中第一位到 character 处并拼接 string, character 为空返回原字符串.(string 字符替换第一个字符到 character 处)
|
||||||
char *splice_head(char *head, const char *character, char *string)
|
char *splice_head(char *head, const char *character, char *string)
|
||||||
{
|
{
|
||||||
int len_first = strlen(string);
|
int len_first = strlen(string);
|
||||||
@ -137,7 +137,7 @@ char *splice_head(char *head, const char *character, char *string)
|
|||||||
return strcat(new_string, p1);
|
return strcat(new_string, p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除字符串head中character到string处, character为空返回原字符串.
|
// 删除字符串 head 中 character 到 string 处, character 为空返回原字符串.
|
||||||
char *delete_head(char *head, const char *character, int string)
|
char *delete_head(char *head, const char *character, int string)
|
||||||
{
|
{
|
||||||
int head_len = strlen(head);
|
int head_len = strlen(head);
|
||||||
@ -158,9 +158,9 @@ char *delete_head(char *head, const char *character, int string)
|
|||||||
|
|
||||||
int extract_host(char *header, char *host, char *port, char *H)
|
int extract_host(char *header, char *host, char *port, char *H)
|
||||||
{
|
{
|
||||||
bzero(host, 0);
|
bzero(host, strlen(host));
|
||||||
bzero(port, 0);
|
bzero(port, strlen(port));
|
||||||
bzero(H, 0);
|
bzero(H, strlen(H));
|
||||||
char *_p = strstr(header, "CONNECT"); // 在 CONNECT 方法中解析 隧道主机名称及端口号
|
char *_p = strstr(header, "CONNECT"); // 在 CONNECT 方法中解析 隧道主机名称及端口号
|
||||||
if (_p) {
|
if (_p) {
|
||||||
char *_p1 = strchr(_p, ' ');
|
char *_p1 = strchr(_p, ' ');
|
||||||
@ -170,8 +170,8 @@ int extract_host(char *header, char *host, char *port, char *H)
|
|||||||
if (_p2) {
|
if (_p2) {
|
||||||
char s_port[10];
|
char s_port[10];
|
||||||
bzero(s_port, 10);
|
bzero(s_port, 10);
|
||||||
strncpy(host, _p1 + 1, (int)(_p2 - _p1) - 1);
|
strncpy_(host, _p1 + 1, (int)(_p2 - _p1) - 1);
|
||||||
strncpy(s_port, _p2 + 1, (int)(_p3 - _p2) - 1);
|
strncpy_(s_port, _p2 + 1, (int)(_p3 - _p2) - 1);
|
||||||
strcpy(port, s_port);
|
strcpy(port, s_port);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -206,7 +206,7 @@ int extract_host(char *header, char *host, char *port, char *H)
|
|||||||
host[h_len] = '\0';
|
host[h_len] = '\0';
|
||||||
} else {
|
} else {
|
||||||
int h_len = (int)(p1 - p - 5 - 1 - 1);
|
int h_len = (int)(p1 - p - 5 - 1 - 1);
|
||||||
strncpy(host, p + 5 + 1, h_len);
|
strncpy_(host, p + 5 + 1, h_len);
|
||||||
host[h_len] = '\0';
|
host[h_len] = '\0';
|
||||||
strcpy(port, "80");
|
strcpy(port, "80");
|
||||||
}
|
}
|
||||||
@ -216,6 +216,18 @@ int extract_host(char *header, char *host, char *port, char *H)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *get_path(char *url, char *path)
|
||||||
|
{
|
||||||
|
if (url) {
|
||||||
|
char *p0 = strstr(url+7, "/");
|
||||||
|
if (p0)
|
||||||
|
return strncpy_(path, p0, strlen(p0));
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
char *request_head(conn *in, conf *configure)
|
char *request_head(conn *in, conf *configure)
|
||||||
{
|
{
|
||||||
const char *method, *path;
|
const char *method, *path;
|
||||||
@ -245,6 +257,8 @@ char *request_head(conn *in, conf *configure)
|
|||||||
char port[path_len];
|
char port[path_len];
|
||||||
char H[path_len*2];
|
char H[path_len*2];
|
||||||
extract_host(in->header_buffer, host, port, H);
|
extract_host(in->header_buffer, host, port, H);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (strncmp(M, "CONNECT", 7) == 0) {
|
if (strncmp(M, "CONNECT", 7) == 0) {
|
||||||
char https_del_copy[configure->https_del_len];
|
char https_del_copy[configure->https_del_len];
|
||||||
@ -276,8 +290,10 @@ char *request_head(conn *in, conf *configure)
|
|||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\r", 2, "\r", 1);
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\r", 2, "\r", 1);
|
||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\n", 2, "\n", 1);
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\n", 2, "\n", 1);
|
||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[M]", 3, M, M_len);
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[M]", 3, M, M_len);
|
||||||
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[method]", 8, M, M_len);
|
||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[U]", 3, U, U_len);
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[U]", 3, U, U_len);
|
||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[V]", 3, V, V_len);
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[V]", 3, V, V_len);
|
||||||
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[version]", 9, V, V_len);
|
||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[host]", 6, host, (int)strlen(host));
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[host]", 6, host, (int)strlen(host));
|
||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[port]", 6, port, (int)strlen(port));
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[port]", 6, port, (int)strlen(port));
|
||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[H]", 3, H, (int)strlen(H));
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[H]", 3, H, (int)strlen(H));
|
||||||
@ -300,7 +316,14 @@ char *request_head(conn *in, conf *configure)
|
|||||||
char https_del_copy[configure->http_del_len];
|
char https_del_copy[configure->http_del_len];
|
||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
int incomplete_head_len;
|
int incomplete_head_len;
|
||||||
|
char url[U_len], uri[U_len];
|
||||||
|
int uri_len;
|
||||||
|
|
||||||
|
|
||||||
|
strcpy(url, U);
|
||||||
|
get_path(url, uri);
|
||||||
|
uri_len = strlen(uri);
|
||||||
|
//printf("%s\n", uri);
|
||||||
if (configure->http_port > 0)
|
if (configure->http_port > 0)
|
||||||
remote_port = configure->http_port;
|
remote_port = configure->http_port;
|
||||||
if (configure->https_ip != NULL)
|
if (configure->https_ip != NULL)
|
||||||
@ -325,8 +348,11 @@ char *request_head(conn *in, conf *configure)
|
|||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\r", 2, "\r", 1);
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\r", 2, "\r", 1);
|
||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\n", 2, "\n", 1);
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "\\n", 2, "\n", 1);
|
||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[M]", 3, M, M_len);
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[M]", 3, M, M_len);
|
||||||
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[method]", 8, M, M_len);
|
||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[U]", 3, U, U_len);
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[U]", 3, U, U_len);
|
||||||
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[uri]", 5, uri, uri_len);
|
||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[V]", 3, V, V_len);
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[V]", 3, V, V_len);
|
||||||
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[version]", 9, V, V_len);
|
||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[host]", 6, host, (int)strlen(host));
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[host]", 6, host, (int)strlen(host));
|
||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[port]", 6, port, (int)strlen(port));
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[port]", 6, port, (int)strlen(port));
|
||||||
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[H]", 3, H, (int)strlen(H));
|
incomplete_head = replace(incomplete_head, &incomplete_head_len, "[H]", 3, H, (int)strlen(H));
|
||||||
|
Loading…
Reference in New Issue
Block a user