Skip to content

Commit

Permalink
feat: check http request method
Browse files Browse the repository at this point in the history
  • Loading branch information
Zxilly committed Oct 31, 2023
1 parent 420762a commit 406c138
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 13 deletions.
2 changes: 1 addition & 1 deletion openwrt/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
include $(TOPDIR)/rules.mk

PKG_NAME:=UA2F
PKG_VERSION:=4.4.0
PKG_VERSION:=4.4.1
PKG_RELEASE:=1

PKG_LICENSE:=GPL-3.0-only
Expand Down
27 changes: 25 additions & 2 deletions src/handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ void handle_packet(struct nf_queue *queue, struct nf_packet *pkt) {

__auto_type tcp_hdr = nfq_tcp_get_hdr(pkt_buff);
if (tcp_hdr == NULL) {
// This packet is not tcp, just pass it
// This packet is not tcp, pass it
send_verdict(queue, pkt, (struct mark_op) {false, 0}, NULL);
syslog(LOG_WARNING, "Received non-tcp packet. You may set wrong firewall rules.");
goto end;
Expand All @@ -239,8 +239,21 @@ void handle_packet(struct nf_queue *queue, struct nf_packet *pkt) {
send_verdict(queue, pkt, get_next_mark(pkt, false), NULL);
goto end;
}

count_tcp_packet();

// cannot find User-Agent: in this packet
if (tcp_payload_len - 2 < USER_AGENT_MATCH_LENGTH) {
send_verdict(queue, pkt, get_next_mark(pkt, false), NULL);
goto end;
}

if (!is_http_protocol(tcp_payload, tcp_payload_len)) {
send_verdict(queue, pkt, get_next_mark(pkt, false), NULL);
goto end;
}
count_http_packet();

void *search_start = tcp_payload;
unsigned int search_length = tcp_payload_len;
bool has_ua = false;
Expand Down Expand Up @@ -298,4 +311,14 @@ void handle_packet(struct nf_queue *queue, struct nf_packet *pkt) {
}

try_print_statistics();
}
}

#undef MAX_USER_AGENT_LENGTH
#undef USER_AGENT_MATCH_LENGTH

#undef CONNMARK_ESTIMATE_LOWER
#undef CONNMARK_ESTIMATE_UPPER
#undef CONNMARK_ESTIMATE_VERDICT

#undef CONNMARK_NOT_HTTP
#undef CONNMARK_HTTP
25 changes: 16 additions & 9 deletions src/statistics.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
#include "statistics.h"

static long long user_agent_packet_count = 0;
static long long http_packet_count = 0;
static long long tcp_packet_count = 0;

static long long ipv4_packet_count = 0;
static long long ipv6_packet_count = 0;
static long long last_report_count = 4;
Expand All @@ -25,6 +27,10 @@ void count_tcp_packet() {
tcp_packet_count++;
}

void count_http_packet() {
http_packet_count++;
}

void count_ipv4_packet() {
ipv4_packet_count++;
}
Expand All @@ -33,33 +39,34 @@ void count_ipv6_packet() {
ipv6_packet_count++;
}

static char TimeStringBuffer[60];
static char time_string_buffer[100];

char *fill_time_string(double sec) {
int s = (int) sec;
memset(TimeStringBuffer, 0, sizeof(TimeStringBuffer));
memset(time_string_buffer, 0, sizeof(time_string_buffer));
if (s <= 60) {
sprintf(TimeStringBuffer, "%d seconds", s);
sprintf(time_string_buffer, "%d seconds", s);
} else if (s <= 3600) {
sprintf(TimeStringBuffer, "%d minutes and %d seconds", s / 60, s % 60);
sprintf(time_string_buffer, "%d minutes and %d seconds", s / 60, s % 60);
} else if (s <= 86400) {
sprintf(TimeStringBuffer, "%d hours, %d minutes and %d seconds", s / 3600, s % 3600 / 60, s % 60);
sprintf(time_string_buffer, "%d hours, %d minutes and %d seconds", s / 3600, s % 3600 / 60, s % 60);
} else {
sprintf(TimeStringBuffer, "%d days, %d hours, %d minutes and %d seconds", s / 86400, s % 86400 / 3600,
sprintf(time_string_buffer, "%d days, %d hours, %d minutes and %d seconds", s / 86400, s % 86400 / 3600,
s % 3600 / 60,
s % 60);
}
return TimeStringBuffer;
return time_string_buffer;
}

void try_print_statistics() {
if (user_agent_packet_count / last_report_count == 2 || user_agent_packet_count - last_report_count >= 16384) {
if (user_agent_packet_count / last_report_count == 2 || user_agent_packet_count - last_report_count >= 8192) {
last_report_count = user_agent_packet_count;
time_t current_t = time(NULL);
syslog(
LOG_INFO,
"UA2F has handled %lld ua http, %lld tcp. %lld ipv4, %lld ipv6 packets in %s.",
"UA2F has handled %lld ua http, %lld http, %lld tcp. %lld ipv4, %lld ipv6 packets in %s.",
user_agent_packet_count,
http_packet_count,
tcp_packet_count,
ipv4_packet_count,
ipv6_packet_count,
Expand Down
2 changes: 2 additions & 0 deletions src/statistics.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ void count_ipv4_packet();

void count_ipv6_packet();

void count_http_packet();

void init_statistics();

void try_print_statistics();
Expand Down
25 changes: 24 additions & 1 deletion src/util.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

void *memncasemem(const void *l, size_t l_len, const void *s, size_t s_len) {
register char *cur, *last;
Expand All @@ -16,7 +17,7 @@ void *memncasemem(const void *l, size_t l_len, const void *s, size_t s_len) {
return NULL;

/* special case where s_len == 1 */
if (s_len == 1){
if (s_len == 1) {
for (cur = (char *) cl; l_len--; cur++)
if (tolower(cur[0]) == tolower(cs[0]))
return cur;
Expand All @@ -33,4 +34,26 @@ void *memncasemem(const void *l, size_t l_len, const void *s, size_t s_len) {
}

return NULL;
}

static bool probe_http_method(const char *p, int len, const char *opt) {
return !strncmp(p, opt, strlen(opt));
}

bool is_http_protocol(const char *p, unsigned int len) {
bool pass = false;

#define PROBE_HTTP_METHOD(opt) if ((pass = probe_http_method(p, len, opt)) != false) return pass

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;
}
2 changes: 2 additions & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
#define UA2F_UTIL_H

#include <string.h>
#include <stdbool.h>

#define QUEUE_NUM 10010

void *memncasemem(const void *l, size_t l_len, const void *s, size_t s_len);
bool is_http_protocol(const char *p, unsigned int len);

#endif //UA2F_UTIL_H
15 changes: 15 additions & 0 deletions test/util_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,19 @@ TEST(MemNCaseMemTest, UserAgentStrange) {
void *result = memncasemem(l, l_len, s, s_len);

EXPECT_EQ(result, (void *) l);
}

TEST(HttpProtocolTest, RealWorldRequests) {
const char* getPayload = "GET /index.html HTTP/1.1\r\nHost: example.com\r\n\r\n";
const char* postPayload = "POST /submit HTTP/1.1\r\nHost: example.com\r\n\r\n";
const char* optionsPayload = "OPTIONS /test HTTP/1.1\r\nHost: example.com\r\n\r\n";

EXPECT_TRUE(is_http_protocol(getPayload, strlen(getPayload))) << "GET method failed";
EXPECT_TRUE(is_http_protocol(postPayload, strlen(postPayload))) << "POST method failed";
EXPECT_TRUE(is_http_protocol(optionsPayload, strlen(optionsPayload))) << "OPTIONS method failed";

const char* invalidPayload = "INVALID string";

// Check that these cases return false
EXPECT_FALSE(is_http_protocol(invalidPayload, strlen(invalidPayload))) << "Invalid method passed";
}

0 comments on commit 406c138

Please sign in to comment.