mirror of
https://github.com/Zxilly/UA2F.git
synced 2026-01-09 11:48:24 +00:00
test new implement
This commit is contained in:
parent
433c8011f9
commit
e5a16108b1
13
.github/workflows/ci.yml
vendored
Normal file
13
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
name: C/C++ CI
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
4
Makefile
4
Makefile
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
169
src/ua2f.c
169
src/ua2f.c
@ -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;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user