prof7bit / udp-reverse-tunnel

Create an UDP-over-UDP reverse tunnel to make a VPN server behind (CG-)NAT accessible from the outside
30 stars 13 forks source link

Trying to build for openwrt with musl instead of glibc curious how many changes would be necessary #1

Closed 46cv8 closed 1 year ago

46cv8 commented 1 year ago

Hey I was hoping to run this on an openwrt router that is built with musl instead of glibc. I am getting a build error that seems indicative that glibc be used instead of musl.

mipsel-openwrt-linux-musl-gcc -MMD -O3 -flto -Wall -Wextra -DVERSION=1.2 -c main.c -o main.o
mipsel-openwrt-linux-musl-gcc -MMD -O3 -flto -Wall -Wextra -DVERSION=1.2 -c connlist.c -o connlist.o
mipsel-openwrt-linux-musl-gcc -MMD -O3 -flto -Wall -Wextra -DVERSION=1.2 -c args.c -o args.o
args.c:2:10: fatal error: argp.h: No such file or directory
    2 | #include <argp.h>
      |          ^~~~~~~~
compilation terminated.
make: *** [Makefile:44: args.o] Error 1

Before I potentially attempt to work around this error, I'm curious if you know what other dependencies there are on glibc that may make this a difficult. The alternative I'm considering right now is using zerotier with a custom standalone planet server and a custom planet file. I do however like this nationalistic approach as I think there is less room for future potential security issues.

Any suggestions you have would be appreciate.

prof7bit commented 1 year ago

argp is only used for parsing the command line arguments. You could either try to find a standalone version of argp (a quick google search indicates that something like this indeed seems to exist) or you could get rid of it entirely and rewrite the command line parsing from scratch.

In main.c right at the beginning it calls the function args_parse() and after this the struct args_parsed_t parsed will contain all the values from the command line. For testing purposes you could replace my args.c implementation with your own, using either hardcoded default values for quick testing purpose or maybe you could implement it using getopt instead of argp.

There is no particular reason that forced me using argp instead of getopt, other than having used argp multiple times before and being somewhat comfortable with it, so it was just convenience on my side.

The only other "special" thing besides argp I'm using is the usage of %m in sscanf() which is a non-standard extension (and this appears also only in args.c), this might or might not work with musl.

After thinking about it for a while it would probably make most sense to just rewrite args.c from scratch.

The actual networking code is only using plain sockets and poll(), so this should not be a problem.

46cv8 commented 1 year ago

Thanks for the reply man! It's been a while since I wrote any c but time permitting I may try to rewrite the arg parsing and see if I can get this building for openwrt. I will update here on my progress, it may take me a little while to get around to it. This would be a really good program to use with openwrt for vpn behind a cgnat. I think zerotier is probably overkill for my purposes and is going to require a monthly vps subscription for the self hosted planet server.

46cv8 commented 1 year ago

Just wanted to update you I did some googleing for argp-standalone and found that it is actually in the openwrt toolchain static link libraries that are available. I enabled it in the "make menuconfig" then I attempted to build your code base again.

I got some different errors but I was able to work around all of them.

diff --git a/Makefile b/Makefile
index 160144b..666ce93 100644
--- a/Makefile
+++ b/Makefile
@@ -7,9 +7,12 @@ name        = udp-tunnel
 version     = 1.2
 objs        = main.o connlist.o args.o sha-256.o mac.o misc.o main-inside.o main-outside.o
 deps        = $(patsubst %.o,%.d,$(objs))
-CFLAGS      = -O3 -flto -Wall -Wextra
+CFLAGS      = -O3 -flto -Wall -Wextra -I/build/openwrt/staging_dir/target-mipsel_24kc_musl/usr/include
+LFLAGS      = -L/build/openwrt/staging_dir/target-mipsel_24kc_musl/usr/lib -largp
 unit_dir    = /etc/systemd/system

+# mipsel-openwrt-linux-musl-gcc -o udp-tunnel -O3 -flto -Wall -Wextra -I/build/openwrt/staging_dir/target-mipsel_24kc_musl/usr/include -DVERSION=1.2 -L/build/openwrt/staging_dir/target-mipsel_24kc_musl/usr/lib main.o connlist.o args.o sha-256.o mac.o misc.o main-inside.o main-outside.o -largp
+
 CFLAGS     += -DVERSION=$(version)

 all: $(name)
diff --git a/main-outside.c b/main-outside.c
index 1caaad6..d9c6cf7 100644
--- a/main-outside.c
+++ b/main-outside.c
@@ -3,6 +3,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/time.h>

 #include "connlist.h"
 #include "mac.h"

The main issue was the linker would continually fail unless -largp appeared after the list of .o object files. So for example the following is working

mipsel-openwrt-linux-musl-gcc -o udp-tunnel -O3 -flto -Wall -Wextra -I/build/openwrt/staging_dir/target-mipsel_24kc_musl/usr/include -DVERSION=1.2 -L/build/openwrt/staging_dir/target-mipsel_24kc_musl/usr/lib main.o connlist.o args.o sha-256.o mac.o misc.o main-inside.o main-outside.o -largp

Whilst the following was failing

mipsel-openwrt-linux-musl-gcc -o udp-tunnel -O3 -flto -Wall -Wextra -I/build/openwrt/staging_dir/target-mipsel_24kc_musl/usr/include -DVERSION=1.2 -L/build/openwrt/staging_dir/target-mipsel_24kc_musl/usr/lib -largp main.o connlist.o args.o sha-256.o mac.o misc.o main-inside.o main-outside.o

There is a discussion of why the linked library name needs to go after the object files at the following page, this is what tipped me off. https://stackoverflow.com/questions/58775599/what-could-be-causing-linking-errors-when-compiling-in-an-alpine-docker

Anyways I managed to test one connection and it seemed to work well :) I'm just providing this feedback incase anyone else tries to use this with openwrt.