test new implement

This commit is contained in:
Zxilly 2021-05-01 22:46:53 +08:00
parent 433c8011f9
commit e5a16108b1
4 changed files with 74 additions and 114 deletions

13
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,13 @@
name: C/C++ CI
on:
push:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

View File

@ -1,9 +1,9 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=UA2F
PKG_VERSION:=2.2
PKG_VERSION:=3.1
PKG_RELEASE:=4
PKG_RELEASE:=5
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)

View File

@ -30,7 +30,7 @@ iptables -t mangle -A ua2f -p tcp --dport 443 -j RETURN
iptables -t mangle -A ua2f -p tcp --dport 22 -j RETURN # 不处理 SSH 和 https
iptables -t mangle -A ua2f -p tcp --dport 80 -j CONNMARK --set-mark 24
iptables -t mangle -A ua2f -m set --set nohttp dst,dst -j RETURN
iptables -t mangle -A ua2f -m connmark --mark 23 -j RETURN # 不处理标记为非 http 的流 (实验性)
iptables -t mangle -A ua2f -m connmark --mark 28 -j RETURN # 不处理标记为非 http 的流 (实验性)
iptables -t mangle -A ua2f -j NFQUEUE --queue-num 10010
iptables -t mangle -A FORWARD -p tcp -m conntrack --ctdir ORIGINAL -j ua2f

View File

@ -20,8 +20,6 @@
#include <libmnl/libmnl.h>
#include <libipset/ipset.h>
// #include <linux/netfilter.h>
#include <linux/netfilter/nfnetlink_queue.h>
#include <libnetfilter_queue/libnetfilter_queue.h>
@ -29,7 +27,6 @@
#include <libnetfilter_queue/libnetfilter_queue_ipv4.h>
#include <libnetfilter_queue/pktbuff.h>
#include <linux/netfilter/nfnetlink_conntrack.h>
#include <errno.h>
#define NF_ACCEPT 1
@ -37,13 +34,13 @@
static struct mnl_socket *nl;
static const int queue_number = 10010;
static long long httpcount = 0;
static long long httpnouacount = 0;
static long long UAcount = 0;
//static long long httpnouacount = 0;
static long long tcpcount = 0;
static long long httpmark = 0;
static long long nohttpmark = 0;
static long long UAmark = 0;
static long long noUAmark = 0;
static long long oldhttpcount = 4;
static long long http1_0count = 0;
//static long long http1_0count = 0;
static time_t start_t, current_t;
@ -80,85 +77,41 @@ static int parse_attrs(const struct nlattr *attr, void *data) {
// static bool http_sign_check(bool firstcheck, unsigned int tcplen, unsigned char *tcppayload);
static bool stringCmp(const char *charp_to, const char charp_from[]) {
return memcmp(charp_to, charp_from, strlen(charp_from)) == 0;
}
static int probe_http_method(const char *p, const char *opt) {
return !strncmp(p, opt, strlen(opt));
}
static bool http_judge(char *tcppayload, unsigned int tcplen) {
// if (*tcppayload < 65 || *tcppayload > 90) { // ASCII
//static int probe_http_method(const char *p, const char *opt) {
// return !strncmp(p, opt, strlen(opt));
//}
//
//static bool http_judge(char *tcppayload, unsigned int tcplen) {
//
// if (tcplen <= 12) {
// return false;
// }
// switch (*tcppayload) {
// case 'G':
// return http_sign_check(stringCmp(tcppayload, "GET"), tcplen, tcppayload);
// case 'P':
// return http_sign_check(
// stringCmp(tcppayload, "POST") || stringCmp(tcppayload, "PUT") || stringCmp(tcppayload, "PATCH"),
// tcplen, tcppayload);
// case 'C':
// return stringCmp(tcppayload, "CONNECT"); // 这个应该有bug
// case 'D':
// return http_sign_check(stringCmp(tcppayload, "DELETE"), tcplen, tcppayload);
// case 'H':
// return http_sign_check(stringCmp(tcppayload, "HEAD"), tcplen, tcppayload);
// case 'T':
// return http_sign_check(stringCmp(tcppayload, "TRACE"), tcplen, tcppayload);
// case 'O':
// return http_sign_check(stringCmp(tcppayload, "OPTIONS"), tcplen, tcppayload);
// default:
// return false;
//
// if (memmem(tcppayload, tcplen, "HTTP", 4)) {
// return true;
// }
if (tcplen <= 12) {
return false;
}
if (memmem(tcppayload, tcplen, "HTTP", 4)) {
return true;
}
#define PROBE_HTTP_METHOD(option) if(probe_http_method(tcppayload, option)) {http1_0count++; return true;}
/* Otherwise it could be HTTP/1.0 without version: check if it's got an
* HTTP method (RFC2616 5.1.1) */
PROBE_HTTP_METHOD("GET ")
PROBE_HTTP_METHOD("POST ")
PROBE_HTTP_METHOD("OPTIONS ")
PROBE_HTTP_METHOD("HEAD ")
PROBE_HTTP_METHOD("PUT ")
PROBE_HTTP_METHOD("DELETE ")
PROBE_HTTP_METHOD("TRACE ")
PROBE_HTTP_METHOD("CONNECT ")
#undef PROBE_HTTP_METHOD
return false;
}
/*static bool http_sign_check(bool firstcheck, const unsigned int tcplen, unsigned char *tcppayload) {
if (!firstcheck) {
return false;
} else {
for (int i = 14; i < tcplen - 3; i++) { //最短的 http 动词是 GET
if (*(tcppayload + i) == '\r') {
if (*(tcppayload + i + 1) == '\n') {
return stringCmp(tcppayload + i - 8, "HTTP/1"); // 向前查找 http 版本
} else {
return false;
}
}
} // 找不到 http 协议版本
return false;
}
}*/
//
//#define PROBE_HTTP_METHOD(option) if(probe_http_method(tcppayload, option)) {http1_0count++; return true;}
//
// /* Otherwise it could be HTTP/1.0 without version: check if it's got an
// * HTTP method (RFC2616 5.1.1) */
// PROBE_HTTP_METHOD("GET ")
// PROBE_HTTP_METHOD("POST ")
// PROBE_HTTP_METHOD("OPTIONS ")
// PROBE_HTTP_METHOD("HEAD ")
// PROBE_HTTP_METHOD("PUT ")
// PROBE_HTTP_METHOD("DELETE ")
// PROBE_HTTP_METHOD("TRACE ")
// PROBE_HTTP_METHOD("CONNECT ")
//
//#undef PROBE_HTTP_METHOD
//
// return false;
//}
static void
nfq_send_verdict(int queue_num, uint32_t id, struct pkt_buff *pktb, uint32_t mark, bool nohttp,
char addcmd[50]) { // http mark = 24, ukn mark = 18-20, no http mark = 23
nfq_send_verdict(int queue_num, uint32_t id, struct pkt_buff *pktb, uint32_t mark, bool noUA,
char addcmd[50]) { // http mark = 24, ukn mark = 16-20, no http mark = 23
char buf[0xffff + (MNL_SOCKET_BUFFER_SIZE / 2)];
struct nlmsghdr *nlh;
struct nlattr *nest;
@ -179,7 +132,7 @@ nfq_send_verdict(int queue_num, uint32_t id, struct pkt_buff *pktb, uint32_t mar
debugflag2++;//flag3
if (nohttp) {
if (noUA) {
if (mark == 1) {
nest = mnl_attr_nest_start(nlh, NFQA_CT);
mnl_attr_put_u32(nlh, CTA_MARK, htonl(16));
@ -201,21 +154,20 @@ nfq_send_verdict(int queue_num, uint32_t id, struct pkt_buff *pktb, uint32_t mar
ipset_parse_line(Pipset, addcmd); //加 ipset 标记
nohttpmark++;
noUAmark++;
}
} else {
if (mark != 24) {
nest = mnl_attr_nest_start(nlh, NFQA_CT);
mnl_attr_put_u32(nlh, CTA_MARK, htonl(24));
mnl_attr_nest_end(nlh, nest);
httpmark++;
UAmark++;
}
}
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
perror("mnl_socket_send");
//exithandle(1);
syslog(LOG_ERR, "Exit at breakpoint 1.");
exit(EXIT_FAILURE);
}
@ -223,9 +175,7 @@ nfq_send_verdict(int queue_num, uint32_t id, struct pkt_buff *pktb, uint32_t mar
debugflag2++;//flag4
tcpcount++;
if (pktb) {
pktb_free(pktb);
}
pktb_free(pktb);
debugflag2++;//flag5
}
@ -248,7 +198,7 @@ static int queue_cb(const struct nlmsghdr *nlh, void *data) {
char *str = NULL;
void *payload;
uint32_t mark = 0;
bool nohttp = false;
bool noUA = false;
char *ip;
uint16_t port = 0;
@ -343,24 +293,21 @@ static int queue_cb(const struct nlmsghdr *nlh, void *data) {
tcppklen = nfq_tcp_get_payload_len(tcppkhdl, pktb); //获取 tcp长度
if (tcppkpayload) {
if (http_judge(tcppkpayload, tcppklen)) {
char *uapointer = memmem(tcppkpayload, tcppklen, "\r\nUser-Agent: ", 14);
if (uapointer) {
debugflag++; //flag5
char *uapointer = memmem(tcppkpayload, tcppklen, "User-Agent:", 11);
debugflag++; //flag6
if (uapointer) {
uaoffset = uapointer - tcppkpayload + 12;
for (int i = 0; i < tcppklen - uaoffset - 4; ++i) {
if (*(uapointer + 12 + i) == '\r') {
ualength = i;
break;
}
uaoffset = uapointer - tcppkpayload + 15;
for (int i = 0; i < tcppklen - uaoffset - 4; ++i) {
if (*(uapointer + 15 + i) == '\r') {
ualength = i;
break;
}
} else {
httpnouacount++;
}
debugflag++; //flag7
@ -382,9 +329,9 @@ static int queue_cb(const struct nlmsghdr *nlh, void *data) {
exit(EXIT_FAILURE);
}
if (nfq_tcp_mangle_ipv4(pktb, uaoffset, ualength, str, ualength) == 1) {
httpcount++; //记录修改包的数量
UAcount++; //记录修改包的数量
free(str);//用完就丢
nohttp = false;
noUA = false;
} else {
free(str);
pktb_free(pktb);
@ -394,22 +341,22 @@ static int queue_cb(const struct nlmsghdr *nlh, void *data) {
debugflag++; //flag8
} else {
nohttp = true;
noUA = true;
}
}
debugflag++; //flag5 / 9
nfq_send_verdict(ntohs(nfg->res_id), ntohl((uint32_t) ph->packet_id), pktb, mark, nohttp, addcmd);
nfq_send_verdict(ntohs(nfg->res_id), ntohl((uint32_t) ph->packet_id), pktb, mark, noUA, addcmd);
debugflag++; //flag6 / 10
if (httpcount / oldhttpcount == 2 || httpcount - oldhttpcount >= 8192) {
oldhttpcount = httpcount;
if (UAcount / oldhttpcount == 2 || UAcount - oldhttpcount >= 8192) {
oldhttpcount = UAcount;
current_t = time(NULL);
syslog(LOG_INFO,
"UA2F has handled %lld http, %lld http 1.0, %lld noua http, %lld tcp. Set %lld mark and %lld nohttp mark in %s",
httpcount, http1_0count, httpnouacount, tcpcount, httpmark, nohttpmark,
"UA2F has handled %lld ua http, %lld tcp. Set %lld mark and %lld noUA mark in %s",
UAcount, tcpcount, UAmark, noUAmark,
time2str((int) difftime(current_t, start_t)));
}
@ -429,7 +376,7 @@ int main(int argc, char *argv[]) {
char *buf;
size_t sizeof_buf = 0xffff + (MNL_SOCKET_BUFFER_SIZE / 2);
struct nlmsghdr *nlh;
int ret;
ssize_t ret;
unsigned int portid;
int child_status;