warp-vpn

point to point VPN implementation
git clone git://git.2f30.org/warp-vpn
Log | Files | Refs | README

commit 376b9d90d05fbf5a4fc54bd624c921bffc437665
parent 2c63a282555e81e9041957631baaaab19fb78545
Author: sin <sin@2f30.org>
Date:   Wed, 22 Mar 2017 13:12:48 +0000

Rename stun to warp-vpn

Diffstat:
MMakefile | 28++++++++++++++--------------
MREADME | 14+++++++-------
Mauth.c | 2+-
Mclient.c | 2+-
Mcrypto.c | 2+-
Mdev_bsd.c | 2+-
Mdev_linux.c | 2+-
Mlog.c | 2+-
Mnetpkt.c | 2+-
Mserver.c | 2+-
Dstun.8 | 67-------------------------------------------------------------------
Dstun.c | 170-------------------------------------------------------------------------------
Dstun.h | 91-------------------------------------------------------------------------------
Mtunnel.c | 2+-
Mutil.c | 2+-
Awarp.8 | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Awarp.c | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Awarp.h | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
18 files changed, 359 insertions(+), 359 deletions(-)

diff --git a/Makefile b/Makefile @@ -15,11 +15,11 @@ DISTFILES = \ log.c \ netpkt.c \ server.c \ - stun.8 \ - stun.c \ - stun.h \ tunnel.c \ - util.c + util.c \ + warp.8 \ + warp.c \ + warp.h OBJ = \ $(EXTRAOBJ) \ @@ -29,18 +29,18 @@ OBJ = \ log.o \ netpkt.o \ server.o \ - stun.o \ tunnel.o \ - util.o + util.o \ + warp.o -BIN = stun +BIN = warp-vpn all: $(BIN) $(BIN): $(OBJ) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(OBJ) $(LDLIBS) -$(OBJ): stun.h +$(OBJ): warp.h install: all mkdir -p $(DESTDIR)$(PREFIX)/bin @@ -53,11 +53,11 @@ uninstall: rm -f $(DESTDIR)$(MANPREFIX)/man8/$(BIN).8 dist: - mkdir -p stun-$(VERSION) - cp $(DISTFILES) stun-$(VERSION) - tar -cf stun-$(VERSION).tar stun-$(VERSION) - gzip stun-$(VERSION).tar - rm -rf stun-$(VERSION) + mkdir -p warp-vpn-$(VERSION) + cp $(DISTFILES) warp-vpn-$(VERSION) + tar -cf warp-vpn-$(VERSION).tar warp-vpn-$(VERSION) + gzip warp-vpn-$(VERSION).tar + rm -rf warp-vpn-$(VERSION) clean: - rm -f $(BIN) $(OBJ) stun-$(VERSION).tar.gz + rm -f $(BIN) $(OBJ) warp-vpn-$(VERSION).tar.gz diff --git a/README b/README @@ -1,5 +1,5 @@ -stun -==== +warp-vpn +======== Installation @@ -16,13 +16,13 @@ On the server: ifconfig tun0 create ifconfig tun0 10.0.0.1 10.0.0.2 - STUNPW=pass stun -s tun0 + PW=pass warp-vpn -s tun0 On the client: ifconfig tun0 create ifconfig tun0 10.0.0.2 10.0.0.1 - STUNPW=pass stun -h hostname tun0 + PW=pass warp-vpn -h hostname tun0 TCP port 12080 must be opened on the server side. @@ -30,11 +30,11 @@ TCP port 12080 must be opened on the server side. Portability ----------- -stun works on OpenBSD, FreeBSD, DragonFly BSD and Linux +warp-vpn works on OpenBSD, FreeBSD, DragonFly BSD and Linux based systems. On FreeBSD and DragonFly BSD you need libressl -to build stun. +to build warp-vpn. On Linux based systems you need libressl and libbsd -to build stun. +to build warp-vpn. diff --git a/auth.c b/auth.c @@ -6,7 +6,7 @@ #include <bsd/stdlib.h> #endif -#include "stun.h" +#include "warp.h" int challenge(int netfd) diff --git a/client.c b/client.c @@ -9,7 +9,7 @@ #include <string.h> #include <unistd.h> -#include "stun.h" +#include "warp.h" int clientconnect(char *host, char *port) diff --git a/crypto.c b/crypto.c @@ -2,7 +2,7 @@ #include <sodium.h> -#include "stun.h" +#include "warp.h" static unsigned char salt[crypto_pwhash_SALTBYTES]; static unsigned char key[crypto_aead_chacha20poly1305_IETF_KEYBYTES]; diff --git a/dev_bsd.c b/dev_bsd.c @@ -17,7 +17,7 @@ #include <stdio.h> #include <unistd.h> -#include "stun.h" +#include "warp.h" int devopen(char *ifname) diff --git a/dev_linux.c b/dev_linux.c @@ -9,7 +9,7 @@ #include <string.h> #include <unistd.h> -#include "stun.h" +#include "warp.h" int devopen(char *ifname) diff --git a/log.c b/log.c @@ -5,7 +5,7 @@ #include <string.h> #include <syslog.h> -#include "stun.h" +#include "warp.h" int debug; diff --git a/netpkt.c b/netpkt.c @@ -7,7 +7,7 @@ #include <bsd/stdlib.h> #endif -#include "stun.h" +#include "warp.h" /* the various states the input handler can be in */ enum { diff --git a/server.c b/server.c @@ -11,7 +11,7 @@ #include <string.h> #include <unistd.h> -#include "stun.h" +#include "warp.h" int serverinit(char *host, char *port) diff --git a/stun.8 b/stun.8 @@ -1,67 +0,0 @@ -.Dd March 22, 2017 -.Dt STUN 8 -.Os -.Sh NAME -.Nm stun -.Nd simple tunnel -.Sh SYNOPSIS -.Nm stun -.Op Fl 46 -.Op Fl d -.Fl s -.Op Fl b Ar address -.Op Fl p Ar port -.Op Fl t Ar devtype -.Op Fl u Ar user -.Ar interface -.Nm stun -.Op Fl 46 -.Op Fl d -.Fl h Ar host -.Op Fl p Ar port -.Op Fl t Ar devtype -.Op Fl u Ar user -.Ar interface -.Sh DESCRIPTION -.Nm -is a simple point to point tunnelling program. There can only be one -client per server. Routing between clients is done by the networking -stack on the server side. -.Sh OPTIONS -.Bl -tag -width "-b address" -.It Fl 4 -Force -.Nm -to use IPv4 addresses only. -.It Fl 6 -Force -.Nm -to use IPv6 addresses only. -.It Fl d -Enable debug output. This will make -.Nm -run in the foreground. -.It Fl s -Enable server mode. Default is off. -.It Fl b Ar address -Bind server to the given -.Ar address . -.It Fl p Ar port -Listen on or connect to specified -.Ar port . -The default port is 12080. -.It Fl h Ar host -Connect to specified -.Ar host . -.It Fl t Ar devtype -Select the tunnel -.Ar device type . -The two available device types are TUN and TAP. The default is TUN. -.It Fl u Ar user -Drop privileges to the specified -.Ar user . -The default user is nobody. -.El -.Sh BUGS -This program is an experiment and may not be secure. Use at your -own risk. diff --git a/stun.c b/stun.c @@ -1,170 +0,0 @@ -/* - * Design overview: - * - * stun implements a point to point encrypted tunnel. It supports - * layer 2 (TAP) and layer 3 (TUN) tunnels. TCP is the only supported - * transport. - * - * stun is a client-server design. There can only be a single client - * connected to the server at any time. Routing between clients is handled - * by the networking stack on the server side. - * - * When a client connects there is a mutual challenge-response phase - * as shown below: - * - * t0: server challenges client - * t1: client responds to server's challenge - * t2: client challenges server - * t3: server responds to client's challenge - * - * The challenge-response algorithm is as follows: - * - * The challenge is a randomly generated 64-bit integer encrypted - * with the pre-shared key and sent to the receiver. - * The receiver decrypts it, adds 1, encrypts it and sends it back to - * the sender. The sender verifies the response. - * This algorithm is the same as what Kerberos uses for authentication. - * - * The stun packet format is shown below: - * - * [NONCE] [PAYLOAD LEN] [PAYLOAD] [TAG] - */ - -#include <sys/resource.h> - -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "arg.h" -#include "stun.h" - -char *argv0; -char *bindaddr; -char *host; -char *port = DEFPORT; -int devtype = TUNDEV; -int aftype = AF_INET; -int sflag; - -void -usage(void) -{ - fprintf(stderr, "usage: stun [-46] [-d] -s [-b address] [-p port] [-t devtype] [-u user] interface\n"); - fprintf(stderr, " stun [-46] [-d] -h host [-p port] [-t devtype] [-u user] interface\n"); - exit(1); -} - -int -main(int argc, char *argv[]) -{ - struct rlimit rlim; - char *arg, *pw; - char *user = NOPRIVUSER; - int devfd, listenfd, netfd; - - ARGBEGIN { - case '4': - aftype = AF_INET; - break; - case '6': - aftype = AF_INET6; - break; - case 'd': - debug = 1; - break; - case 's': - sflag = 1; - break; - case 'b': - bindaddr = EARGF(usage()); - break; - case 'h': - host = EARGF(usage()); - break; - case 'p': - port = EARGF(usage()); - break; - case 't': - arg = EARGF(usage()); - if (strcasecmp(arg, "tun") == 0) - devtype = TUNDEV; - else if (strcasecmp(arg, "tap") == 0) - devtype = TAPDEV; - else - usage(); - break; - case 'u': - user = EARGF(usage()); - break; - default: - usage(); - } ARGEND - - if (argc != 1 || !(sflag ^ (host != NULL))) - usage(); - - loginit("stun"); - - /* disable core dumps as memory contains the pre-shared key */ - rlim.rlim_cur = rlim.rlim_max = 0; - if (setrlimit(RLIMIT_CORE, &rlim) < 0) - fatalx("failed to disable core dumps"); - - signal(SIGPIPE, SIG_IGN); - if (!debug) - daemon(0, 0); - - /* initialize tun/tap device */ - devfd = devopen(argv[0]); - - /* initialize crypto engine */ - if (!(pw = getenv("STUNPW"))) - fatalx("STUNPW is not set"); - cryptoinit(); - derivekey(pw); - memset(pw, 0, strlen(pw)); - - /* initialize networking engine */ - netinit(); - - if (sflag) { - /* invoked as server */ - listenfd = serverinit(bindaddr, port); - revokeprivs(user); - if (mypledge("stdio inet", NULL) < 0) - fatal("pledge"); - for (;;) { - if ((netfd = serveraccept(listenfd)) < 0) { - netreset(); - continue; - } - logdbgx("client %s is ready", peer_ntop(netfd)); - tunnel(netfd, devfd); - logdbgx("client %s disconnected", peer_ntop(netfd)); - close(netfd); - netreset(); - } - } else { - /* invoked as client */ - revokeprivs(user); - if (mypledge("stdio dns inet", NULL) < 0) - fatal("pledge"); - for (;;) { - if ((netfd = clientconnect(host, port)) < 0) { - netreset(); - sleep(RECONNECTTIMEO); - continue; - } - logdbgx("connected to %s", peer_ntop(netfd)); - tunnel(netfd, devfd); - logdbgx("disconnected from %s", peer_ntop(netfd)); - close(netfd); - netreset(); - sleep(RECONNECTTIMEO); - } - } - return 0; -} diff --git a/stun.h b/stun.h @@ -1,91 +0,0 @@ -#include <sys/socket.h> - -#include <stddef.h> -#include <stdint.h> - -#define NOPRIVUSER "nobody" -#define AUTHTIMEO 10 /* in seconds */ -#define RECONNECTTIMEO 60 /* in seconds */ -#define HDRLEN 2 -#define MAXPAYLOADLEN 1404 -#define NROUNDS 100000 -#define DEFPORT "12080" - -enum { - PKTFAILED, - PKTPARTIAL, - PKTCOMPLETE -}; - -enum { - TUNDEV, - TAPDEV -}; - -/* log.c */ -extern int debug; - -/* stun.c */ -extern int devtype; -extern int aftype; -extern int debug; - -/* auth.c */ -int challenge(int); -int response(int); - -/* client.c */ -int clientconnect(char *, char *); - -/* crypto.c */ -void cryptoinit(void); -void derivekey(char *); -size_t cryptononcelen(void); -size_t cryptotaglen(void); -int cryptoseal(unsigned char *, unsigned long long *, - const unsigned char *, unsigned long long, - const unsigned char *, unsigned long long, - const unsigned char *); -int cryptoopen(unsigned char *, unsigned long long *, - const unsigned char *, unsigned long long, - const unsigned char *, unsigned long long, - const unsigned char *); - -/* dev_*.c */ -int devopen(char *); -int devwrite(int, unsigned char *, int); -int devread(int, unsigned char *, int); - -/* log.c */ -void loginit(char *); -void logdbg(char *, ...); -void logdbgx(char *, ...); -void logwarn(char *, ...); -void logwarnx(char *, ...); -void fatal(char *, ...); -void fatalx(char *, ...); - -/* netpkt.c */ -int netwrite(int, unsigned char *, unsigned long long, unsigned long long *); -int netread(int, unsigned char *, unsigned long long, unsigned long long *); -void netreset(void); -void netinit(void); - -/* server.c */ -int serverinit(char *, char *); -int serveraccept(int); - -/* tunnel.c */ -int tunnel(int, int); - -/* util.c */ -void pack16(unsigned char *, uint16_t); -uint16_t unpack16(unsigned char *); -void pack64(unsigned char *, uint64_t); -uint64_t unpack64(unsigned char *); -void revokeprivs(char *); -int setnonblock(int, int); -char *saddr_ntop(struct sockaddr *, socklen_t); -char *peer_ntop(int); -int ipversion(unsigned char *); -int mypledge(const char *, const char *[]); diff --git a/tunnel.c b/tunnel.c @@ -1,6 +1,6 @@ #include <poll.h> -#include "stun.h" +#include "warp.h" int tunnel(int netfd, int devfd) diff --git a/util.c b/util.c @@ -11,7 +11,7 @@ #include <stdio.h> #include <unistd.h> -#include "stun.h" +#include "warp.h" void pack16(unsigned char *buf, uint16_t n) diff --git a/warp.8 b/warp.8 @@ -0,0 +1,67 @@ +.Dd March 22, 2017 +.Dt WARP-VPN 8 +.Os +.Sh NAME +.Nm warp-vpn +.Nd simple tunnel +.Sh SYNOPSIS +.Nm warp-vpn +.Op Fl 46 +.Op Fl d +.Fl s +.Op Fl b Ar address +.Op Fl p Ar port +.Op Fl t Ar devtype +.Op Fl u Ar user +.Ar interface +.Nm warp-vpn +.Op Fl 46 +.Op Fl d +.Fl h Ar host +.Op Fl p Ar port +.Op Fl t Ar devtype +.Op Fl u Ar user +.Ar interface +.Sh DESCRIPTION +.Nm +is a simple point to point tunnelling program. There can only be one +client per server. Routing between clients is done by the networking +stack on the server side. +.Sh OPTIONS +.Bl -tag -width "-b address" +.It Fl 4 +Force +.Nm +to use IPv4 addresses only. +.It Fl 6 +Force +.Nm +to use IPv6 addresses only. +.It Fl d +Enable debug output. This will make +.Nm +run in the foreground. +.It Fl s +Enable server mode. Default is off. +.It Fl b Ar address +Bind server to the given +.Ar address . +.It Fl p Ar port +Listen on or connect to specified +.Ar port . +The default port is 12080. +.It Fl h Ar host +Connect to specified +.Ar host . +.It Fl t Ar devtype +Select the tunnel +.Ar device type . +The two available device types are TUN and TAP. The default is TUN. +.It Fl u Ar user +Drop privileges to the specified +.Ar user . +The default user is nobody. +.El +.Sh BUGS +This program is an experiment and may not be secure. Use at your +own risk. diff --git a/warp.c b/warp.c @@ -0,0 +1,170 @@ +/* + * Design overview: + * + * warp-vpn implements a point to point encrypted tunnel. It supports + * layer 2 (TAP) and layer 3 (TUN) tunnels. TCP is the only supported + * transport. + * + * warp-vpn is a client-server design. There can only be a single client + * connected to the server at any time. Routing between clients is handled + * by the networking stack on the server side. + * + * When a client connects there is a mutual challenge-response phase + * as shown below: + * + * t0: server challenges client + * t1: client responds to server's challenge + * t2: client challenges server + * t3: server responds to client's challenge + * + * The challenge-response algorithm is as follows: + * + * The challenge is a randomly generated 64-bit integer encrypted + * with the pre-shared key and sent to the receiver. + * The receiver decrypts it, adds 1, encrypts it and sends it back to + * the sender. The sender verifies the response. + * This algorithm is the same as what Kerberos uses for authentication. + * + * The warp-vpn packet format is shown below: + * + * [NONCE] [PAYLOAD LEN] [PAYLOAD] [TAG] + */ + +#include <sys/resource.h> + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "arg.h" +#include "warp.h" + +char *argv0; +char *bindaddr; +char *host; +char *port = DEFPORT; +int devtype = TUNDEV; +int aftype = AF_INET; +int sflag; + +void +usage(void) +{ + fprintf(stderr, "usage: warp-vpn [-46] [-d] -s [-b address] [-p port] [-t devtype] [-u user] interface\n"); + fprintf(stderr, " warp-vpn [-46] [-d] -h host [-p port] [-t devtype] [-u user] interface\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + struct rlimit rlim; + char *arg, *pw; + char *user = NOPRIVUSER; + int devfd, listenfd, netfd; + + ARGBEGIN { + case '4': + aftype = AF_INET; + break; + case '6': + aftype = AF_INET6; + break; + case 'd': + debug = 1; + break; + case 's': + sflag = 1; + break; + case 'b': + bindaddr = EARGF(usage()); + break; + case 'h': + host = EARGF(usage()); + break; + case 'p': + port = EARGF(usage()); + break; + case 't': + arg = EARGF(usage()); + if (strcasecmp(arg, "tun") == 0) + devtype = TUNDEV; + else if (strcasecmp(arg, "tap") == 0) + devtype = TAPDEV; + else + usage(); + break; + case 'u': + user = EARGF(usage()); + break; + default: + usage(); + } ARGEND + + if (argc != 1 || !(sflag ^ (host != NULL))) + usage(); + + loginit("warp-vpn"); + + /* disable core dumps as memory contains the pre-shared key */ + rlim.rlim_cur = rlim.rlim_max = 0; + if (setrlimit(RLIMIT_CORE, &rlim) < 0) + fatalx("failed to disable core dumps"); + + signal(SIGPIPE, SIG_IGN); + if (!debug) + daemon(0, 0); + + /* initialize tun/tap device */ + devfd = devopen(argv[0]); + + /* initialize crypto engine */ + if (!(pw = getenv("PW"))) + fatalx("PW is not set"); + cryptoinit(); + derivekey(pw); + memset(pw, 0, strlen(pw)); + + /* initialize networking engine */ + netinit(); + + if (sflag) { + /* invoked as server */ + listenfd = serverinit(bindaddr, port); + revokeprivs(user); + if (mypledge("stdio inet", NULL) < 0) + fatal("pledge"); + for (;;) { + if ((netfd = serveraccept(listenfd)) < 0) { + netreset(); + continue; + } + logdbgx("client %s is ready", peer_ntop(netfd)); + tunnel(netfd, devfd); + logdbgx("client %s disconnected", peer_ntop(netfd)); + close(netfd); + netreset(); + } + } else { + /* invoked as client */ + revokeprivs(user); + if (mypledge("stdio dns inet", NULL) < 0) + fatal("pledge"); + for (;;) { + if ((netfd = clientconnect(host, port)) < 0) { + netreset(); + sleep(RECONNECTTIMEO); + continue; + } + logdbgx("connected to %s", peer_ntop(netfd)); + tunnel(netfd, devfd); + logdbgx("disconnected from %s", peer_ntop(netfd)); + close(netfd); + netreset(); + sleep(RECONNECTTIMEO); + } + } + return 0; +} diff --git a/warp.h b/warp.h @@ -0,0 +1,91 @@ +#include <sys/socket.h> + +#include <stddef.h> +#include <stdint.h> + +#define NOPRIVUSER "nobody" +#define AUTHTIMEO 10 /* in seconds */ +#define RECONNECTTIMEO 60 /* in seconds */ +#define HDRLEN 2 +#define MAXPAYLOADLEN 1404 +#define NROUNDS 100000 +#define DEFPORT "12080" + +enum { + PKTFAILED, + PKTPARTIAL, + PKTCOMPLETE +}; + +enum { + TUNDEV, + TAPDEV +}; + +/* log.c */ +extern int debug; + +/* warp.c */ +extern int devtype; +extern int aftype; +extern int debug; + +/* auth.c */ +int challenge(int); +int response(int); + +/* client.c */ +int clientconnect(char *, char *); + +/* crypto.c */ +void cryptoinit(void); +void derivekey(char *); +size_t cryptononcelen(void); +size_t cryptotaglen(void); +int cryptoseal(unsigned char *, unsigned long long *, + const unsigned char *, unsigned long long, + const unsigned char *, unsigned long long, + const unsigned char *); +int cryptoopen(unsigned char *, unsigned long long *, + const unsigned char *, unsigned long long, + const unsigned char *, unsigned long long, + const unsigned char *); + +/* dev_*.c */ +int devopen(char *); +int devwrite(int, unsigned char *, int); +int devread(int, unsigned char *, int); + +/* log.c */ +void loginit(char *); +void logdbg(char *, ...); +void logdbgx(char *, ...); +void logwarn(char *, ...); +void logwarnx(char *, ...); +void fatal(char *, ...); +void fatalx(char *, ...); + +/* netpkt.c */ +int netwrite(int, unsigned char *, unsigned long long, unsigned long long *); +int netread(int, unsigned char *, unsigned long long, unsigned long long *); +void netreset(void); +void netinit(void); + +/* server.c */ +int serverinit(char *, char *); +int serveraccept(int); + +/* tunnel.c */ +int tunnel(int, int); + +/* util.c */ +void pack16(unsigned char *, uint16_t); +uint16_t unpack16(unsigned char *); +void pack64(unsigned char *, uint64_t); +uint64_t unpack64(unsigned char *); +void revokeprivs(char *); +int setnonblock(int, int); +char *saddr_ntop(struct sockaddr *, socklen_t); +char *peer_ntop(int); +int ipversion(unsigned char *); +int mypledge(const char *, const char *[]);