From 82fa9502894057c0df629df419763469b3c193ab Mon Sep 17 00:00:00 2001 From: ge9 <37699433+ge9@users.noreply.github.com> Date: Sat, 29 Jun 2024 23:46:19 +0900 Subject: [PATCH] added support for FreeBSD/OpenBSD (#201) --- Makefile | 11 ++++++++++- base.c | 2 +- libc-compat.h | 2 +- redsocks.c | 2 +- redudp.c | 32 +++++++++++++++++++++++++++++++- socks5-udp.c | 4 ++++ tcpdns.c | 2 +- utils.c | 15 +++++++++++++++ 8 files changed, 64 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 70237a24..b8c1f8aa 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,9 @@ endif ifeq ($(OS), FreeBSD) override CFLAGS +=-I/usr/local/include -L/usr/local//lib endif +ifeq ($(OS), OpenBSD) +override CFLAGS +=-I/usr/local/include -L/usr/local//lib #same as FreeBSD +endif ifeq ($(OS), Darwin) override CFLAGS +=-I/usr/local/opt/openssl/include -L/usr/local/opt/openssl/lib SHELL := /bin/bash @@ -52,7 +55,10 @@ override CFLAGS += -DENABLE_HTTPS_PROXY override FEATURES += ENABLE_HTTPS_PROXY $(info Compile with HTTPS proxy enabled.) endif -override LIBS += -lssl -lcrypto -ldl +override LIBS += -lssl -lcrypto +ifneq ($(OS), OpenBSD) +override LIBS += -ldl +endif override CFLAGS += -DUSE_CRYPTO_OPENSSL endif ifdef ENABLE_STATIC @@ -79,6 +85,9 @@ $(CONF): OpenBSD) \ echo "#define USE_PF" >$(CONF) \ ;; \ + NetBSD) \ + echo "#define USE_PF" >$(CONF) \ + ;; \ Darwin) \ echo -e "#define USE_PF\n#define _APPLE_" >$(CONF) \ ;; \ diff --git a/base.c b/base.c index edacfa94..ed6af4b5 100644 --- a/base.c +++ b/base.c @@ -95,7 +95,7 @@ static base_instance instance = { .log_info = false, }; -#if defined __FreeBSD__ || defined USE_PF +#if defined __FreeBSD__ || defined USE_PF || defined __OpenBSD__ || defined __NetBSD__ static int redir_open_private(const char *fname, int flags) { int fd = open(fname, flags); diff --git a/libc-compat.h b/libc-compat.h index eb4b340c..02b28390 100644 --- a/libc-compat.h +++ b/libc-compat.h @@ -42,7 +42,7 @@ # define SOL_IP IPPROTO_IP #endif -#ifdef __FreeBSD__ +#if defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ #ifndef INADDR_LOOPBACK # warning Using hardcoded value for INADDR_LOOPBACK for FreeBSD. # define INADDR_LOOPBACK 0x7F000001 diff --git a/redsocks.c b/redsocks.c index 14c91a4a..2a089d37 100644 --- a/redsocks.c +++ b/redsocks.c @@ -1022,7 +1022,7 @@ static int redsocks_init_instance(redsocks_instance *instance) if (apply_reuseport(fd)) log_error(LOG_WARNING, "Continue without SO_REUSEPORT enabled"); -#if defined(__APPLE__) || defined(__FreeBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) bindaddr_len = instance->config.bindaddr.ss_len > 0 ? instance->config.bindaddr.ss_len : sizeof(instance->config.bindaddr); #else bindaddr_len = sizeof(instance->config.bindaddr); diff --git a/redudp.c b/redudp.c index 1434c776..6f088b31 100644 --- a/redudp.c +++ b/redudp.c @@ -1,3 +1,4 @@ + /* redsocks2 - transparent TCP/UDP-to-proxy redirector * Copyright (C) 2013-2017 Zhuofei Wang * @@ -133,6 +134,22 @@ static int bound_udp_get(const struct sockaddr *addr) node->key = key; node->ref = 1; node->fd = socket(addr->sa_family, SOCK_DGRAM, IPPROTO_UDP); +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) + int on = 1; +#if defined(__FreeBSD__) +#ifdef SOL_IPV6 + if (addr->sa_family == AF_INET) { +#endif + setsockopt(node->fd, IPPROTO_IP, IP_BINDANY, &on, sizeof(on)); +#ifdef SOL_IPV6 + } else { + setsockopt(node->fd, IPPROTO_IPV6, IPV6_BINDANY, &on, sizeof(on)); + } +#endif +#else + setsockopt(node->fd, SOL_SOCKET, SO_BINDANY, &on, sizeof(on)); +#endif +#endif node->t_last_rx = redsocks_time(NULL); if (node->fd == -1) { log_errno(LOG_ERR, "socket"); @@ -300,8 +317,13 @@ void redudp_fwd_pkt_to_sender(redudp_client *client, void *buf, size_t len, } // TODO: record remote address in client + sent = sendto(fd, buf, len, 0, +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) + (struct sockaddr*)&client->clientaddr, sizeof(struct sockaddr_in)); +#else (struct sockaddr*)&client->clientaddr, sizeof(client->clientaddr)); +#endif if (sent != len) { redudp_log_error( client, @@ -638,6 +660,10 @@ static int redudp_init_instance(redudp_instance *instance) log_errno(LOG_ERR, "setsockopt(listener, SOL_IP, IP_RECVORIGDSTADDR)"); goto fail; } +#if defined(__OpenBSD__) || defined(__NetBSD__) + setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on)); + setsockopt(fd, IPPROTO_IP, IP_RECVDSTPORT, &on, sizeof(on)); +#endif #ifdef SOL_IPV6 } else { @@ -646,6 +672,10 @@ static int redudp_init_instance(redudp_instance *instance) log_errno(LOG_ERR, "setsockopt(listener, SOL_IPV6, IPV6_RECVORIGDSTADDR)"); goto fail; } +#if defined(__OpenBSD__) || defined(__NetBSD__) + setsockopt(fd, IPPROTO_IP, IPV6_RECVPKTINFO, &on, sizeof(on)); + setsockopt(fd, IPPROTO_IP, IPV6_RECVDSTPORT, &on, sizeof(on)); +#endif } #endif log_error(LOG_INFO, "redudp @ %s: TPROXY", red_inet_ntop(&instance->config.bindaddr, buf1, sizeof(buf1))); @@ -660,7 +690,7 @@ static int redudp_init_instance(redudp_instance *instance) if (apply_reuseport(fd)) log_error(LOG_WARNING, "Continue without SO_REUSEPORT enabled"); -#if defined(__APPLE__) || defined(__FreeBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) bindaddr_len = instance->config.bindaddr.ss_len > 0 ? instance->config.bindaddr.ss_len : sizeof(instance->config.bindaddr); #else bindaddr_len = sizeof(instance->config.bindaddr); diff --git a/socks5-udp.c b/socks5-udp.c index 5666e024..66544ec1 100644 --- a/socks5-udp.c +++ b/socks5-udp.c @@ -312,7 +312,11 @@ static void socks5_read_assoc_reply(struct bufferevent *buffev, void *_arg) goto fail; } +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) + error = connect(fd, (struct sockaddr*)&socks5client->udprelayaddr, sizeof(struct sockaddr_in)); +#else error = connect(fd, (struct sockaddr*)&socks5client->udprelayaddr, sizeof(socks5client->udprelayaddr)); +#endif if (error) { redudp_log_errno(client, LOG_NOTICE, "connect"); goto fail; diff --git a/tcpdns.c b/tcpdns.c index 7d15f8d9..1b2d744a 100644 --- a/tcpdns.c +++ b/tcpdns.c @@ -463,7 +463,7 @@ static int tcpdns_init_instance(tcpdns_instance *instance) if (apply_reuseport(fd)) log_error(LOG_WARNING, "Continue without SO_REUSEPORT enabled"); -#if defined(__APPLE__) || defined(__FreeBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) bindaddr_len = instance->config.bindaddr.ss_len > 0 ? instance->config.bindaddr.ss_len : sizeof(instance->config.bindaddr); #else bindaddr_len = sizeof(instance->config.bindaddr); diff --git a/utils.c b/utils.c index 5ef8386b..7600b2ed 100644 --- a/utils.c +++ b/utils.c @@ -98,14 +98,29 @@ int red_recv_udp_pkt( } break; } +#if defined(__OpenBSD__) || defined(__NetBSD__) + //TODO: support IPv6 + else if (cmsg->cmsg_type == IP_RECVDSTADDR || cmsg->cmsg_type == IP_RECVDSTPORT){ + struct sockaddr* cmsgaddr = (struct sockaddr*)CMSG_DATA(cmsg); + toaddr->ss_family=AF_INET; + struct sockaddr_in *toaddr_in = (struct sockaddr_in *)toaddr; + if (cmsg->cmsg_type == IP_RECVDSTADDR) { + memcpy(&toaddr_in->sin_addr, cmsgaddr, sizeof(struct in_addr)); + } else if (cmsg->cmsg_type == IP_RECVDSTPORT) { + memcpy(&toaddr_in->sin_port, cmsgaddr, sizeof(in_port_t)); + } + } +#endif else { log_error(LOG_WARNING, "unexepcted cmsg (level,type) = (%d,%d)", cmsg->cmsg_level, cmsg->cmsg_type); } } if (toaddr->ss_family == 0) { +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) log_error(LOG_WARNING, "(SOL_IP, IP_ORIGDSTADDR) not found"); return -1; +#endif } }