From e8b193f0c2cb3232dd769bc62ebf03afc80525c6 Mon Sep 17 00:00:00 2001 From: Zxilly Date: Mon, 1 Jul 2024 04:10:46 +0800 Subject: [PATCH] fix: add fail fallback for no conntrack environment --- src/cli.c | 14 +++++++++++--- src/cli.h | 2 ++ src/handler.c | 4 ++-- src/handler.h | 2 ++ src/third/nfqueue-mnl.c | 13 ++++++++----- src/third/nfqueue-mnl.h | 2 +- src/ua2f.c | 26 ++++++++++++++++++++++++-- 7 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/cli.c b/src/cli.c index 3957c58..be92266 100644 --- a/src/cli.c +++ b/src/cli.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "cli.h" #include "config.h" @@ -31,19 +32,26 @@ void try_print_info(const int argc, char *argv[]) { #else printf("UCI support disabled\n"); #endif - exit(0); + exit(EXIT_SUCCESS); } if (strcmp(argv[1], "--help") == 0) { printf("Usage: ua2f\n"); printf(" --version\n"); printf(" --help\n"); - exit(0); + exit(EXIT_SUCCESS); } printf("Unknown option: %s\n", argv[1]); printf("Usage: ua2f\n"); printf(" --version\n"); printf(" --help\n"); - exit(1); + exit(EXIT_FAILURE); } + +void require_root() { + if (geteuid() != 0) { + fprintf(stderr, "This program must be run as root\n"); + exit(EXIT_FAILURE); + } +} \ No newline at end of file diff --git a/src/cli.h b/src/cli.h index f28642d..c8da5a1 100644 --- a/src/cli.h +++ b/src/cli.h @@ -21,4 +21,6 @@ void try_print_info(int argc, char *argv[]); +void require_root(); + #endif // UA2F_CLI_H diff --git a/src/handler.c b/src/handler.c index 0409045..78dea46 100644 --- a/src/handler.c +++ b/src/handler.c @@ -68,7 +68,7 @@ static void send_verdict(const struct nf_queue *queue, const struct nf_packet *p syslog(LOG_ERR, "failed to put nfqueue header"); goto end; } - nfq_nlmsg_verdict_put(nlh, (int)pkt->packet_id, NF_ACCEPT); + nfq_nlmsg_verdict_put(nlh, pkt->packet_id, NF_ACCEPT); if (mark.should_set) { struct nlattr *nest = mnl_attr_nest_start_check(nlh, SEND_BUF_LEN, NFQA_CT); @@ -98,7 +98,7 @@ end: } } -static bool conntrack_info_available = true; +bool conntrack_info_available = true; static bool cache_initialized = false; static void add_to_cache(const struct nf_packet *pkt) { diff --git a/src/handler.h b/src/handler.h index 6b2ec79..7be7341 100644 --- a/src/handler.h +++ b/src/handler.h @@ -3,6 +3,8 @@ #include "third/nfqueue-mnl.h" +extern bool conntrack_info_available; + void init_handler(); void handle_packet(const struct nf_queue *queue, const struct nf_packet *pkt); diff --git a/src/third/nfqueue-mnl.c b/src/third/nfqueue-mnl.c index e6ba4d8..05aa331 100644 --- a/src/third/nfqueue-mnl.c +++ b/src/third/nfqueue-mnl.c @@ -80,7 +80,8 @@ struct nlmsghdr *nfqueue_put_header(int queue_num, int msg_type) { void *buf = malloc(SEND_BUF_LEN); ASSERT(buf != NULL); struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); - ASSERT(nlh == buf); + ASSERT(nlh != NULL); // fixme: workaround CLion bug + nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | msg_type; nlh->nlmsg_flags = NLM_F_REQUEST; @@ -566,7 +567,7 @@ nfqueue_receive() while packet object is being processed by another thread. // Return false on failure // If queue_len is zero, use default value -bool nfqueue_open(struct nf_queue *q, int queue_num, uint32_t queue_len) { +bool nfqueue_open(struct nf_queue *q, int queue_num, uint32_t queue_len, bool skip_conntrack) { memset(q, 0, sizeof(*q)); q->queue_num = queue_num; @@ -596,9 +597,11 @@ bool nfqueue_open(struct nf_queue *q, int queue_num, uint32_t queue_len) { In kernel 4.15 modprobe-only method is not sufficient, rule containing -m conntrack must be used. Otherwise, conntrack info is not passed by kernel (both NFQA_CT and NFQA_CT_INFO attributes are missing). */ - if (nfqueue_set_params(q->nl_socket, queue_num, NFQNL_COPY_PACKET, 0xFFFF, queue_len, NFQA_CFG_F_CONNTRACK) < 0) { - LOG_SYSERR("nfqueue_set_params"); - return false; + if (!skip_conntrack) { + if (nfqueue_set_params(q->nl_socket, queue_num, NFQNL_COPY_PACKET, 0xFFFF, queue_len, NFQA_CFG_F_CONNTRACK) < 0) { + LOG_SYSERR("nfqueue_set_params"); + return false; + } } ssize_t sockopt = 1; diff --git a/src/third/nfqueue-mnl.h b/src/third/nfqueue-mnl.h index f439f98..e4a3c79 100644 --- a/src/third/nfqueue-mnl.h +++ b/src/third/nfqueue-mnl.h @@ -240,7 +240,7 @@ nfqueue_receive() while packet object is being processed by another thread. // Return false on failure // If queue_len is zero, use default value -bool nfqueue_open(struct nf_queue *q, int queue_num, uint32_t queue_len); +bool nfqueue_open(struct nf_queue *q, int queue_num, uint32_t queue_len, bool skip_conntrack); void nfqueue_close(struct nf_queue *q); diff --git a/src/ua2f.c b/src/ua2f.c index 4116108..2426d0b 100644 --- a/src/ua2f.c +++ b/src/ua2f.c @@ -50,12 +50,32 @@ int read_buffer(struct nf_queue *queue, struct nf_buffer *buf) { } } +bool retry_disable_conntrack(struct nf_queue *queue) { + nfqueue_close(queue); + + syslog(LOG_INFO, "Retrying to disable conntrack"); + const __auto_type ret = nfqueue_open(queue, QUEUE_NUM, 0, true); + if (!ret) { + syslog(LOG_ERR, "Failed to open nfqueue with conntrack disabled"); + return false; + } + return true; +} + void main_loop(struct nf_queue *queue) { struct nf_buffer buf[1] = {0}; + bool retried = false; while (!should_exit) { if (read_buffer(queue, buf) == IO_ERROR) { - break; + if (!retried) { + retried = true; + if (!retry_disable_conntrack(queue)) { + break; + } + } else { + break; + } } } @@ -73,6 +93,8 @@ int main(const int argc, char *argv[]) { try_print_info(argc, argv); + require_root(); + init_statistics(); init_handler(); @@ -84,7 +106,7 @@ int main(const int argc, char *argv[]) { struct nf_queue queue[1] = {0}; - const __auto_type ret = nfqueue_open(queue, QUEUE_NUM, 0); + const __auto_type ret = nfqueue_open(queue, QUEUE_NUM, 0, false); if (!ret) { syslog(LOG_ERR, "Failed to open nfqueue"); return EXIT_FAILURE;