Compare commits

..

30 Commits

Author SHA1 Message Date
Adrien Gallouët
d1940692b2 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-26 14:11:36 +00:00
Adrien Gallouët
d3307a22f8 Add missing netinet/in.h (for freebsd)
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-26 14:02:53 +00:00
Adrien Gallouët
93cefd6dba Dependency systemd is not mandatory
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-26 13:52:20 +00:00
Adrien Gallouët
21718c8c14 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-26 13:22:51 +00:00
Adrien Gallouët
aa54a72bbc Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-26 13:18:07 +00:00
Adrien Gallouët
32e6e7575a Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-26 13:13:37 +00:00
Adrien Gallouët
19eea3e96d Add a start section in glorytun-setup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-26 12:44:13 +00:00
Adrien Gallouët
75b2903ac2 Add unit systemd files
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-26 08:23:25 +00:00
Adrien Gallouët
0f5a6f5d98 Update .gitignore
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-17 14:43:55 +00:00
Adrien Gallouët
ed90fdea02 Cleanup meson build
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-17 14:42:56 +00:00
Adrien Gallouët
520bd33cb3 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-17 08:35:31 +00:00
Adrien Gallouët
361c695c5c Remove .build.sh
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-17 08:33:44 +00:00
Adrien Gallouët
bc5d622169 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-17 08:32:48 +00:00
Adrien Gallouët
7859746f66 Add meson.build
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-17 08:19:22 +00:00
Adrien Gallouët
c3b8c44c68 Show only version
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-17 08:18:30 +00:00
Adrien Gallouët
297e93ed54 Add persist option
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-16 15:52:30 +00:00
Adrien Gallouët
325575c6a7 Update mud and add option keygen
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-16 15:20:11 +00:00
Adrien Gallouët
3b1c9db3f8 Remove gt_na() and gt_fatal()
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2017-11-15 23:31:17 +00:00
Adrien Gallouët
557d3f7869 Update mud 2017-03-07 10:46:38 +00:00
Adrien Gallouët
195908d379 Add iface.[ch] 2017-03-07 10:36:23 +00:00
Adrien Gallouët
eb5c6853c1 Allow undefined PACKAGE_STRING 2017-03-07 10:36:16 +00:00
Adrien Gallouët
3c2481dc33 Allow undefined TUNSETPERSIST 2017-02-10 15:13:05 +00:00
Adrien Gallouët
355040f576 Don't destroy tun on SIGHUP 2017-02-10 11:54:19 +00:00
Adrien Gallouët
bbf1c12f7a Update mud 2017-01-29 12:03:27 +00:00
Adrien Gallouët
c54303da8f Update mud 2017-01-20 09:53:58 +00:00
Adrien Gallouët
e3440cf1e9 Update mud 2017-01-19 14:55:09 +00:00
Adrien Gallouët
86916f1999 Add buf-size option and increase buffer size 2017-01-19 14:13:29 +00:00
Adrien Gallouët
9cebabfe01 Remove while(1) 2017-01-19 12:47:06 +00:00
Adrien Gallouët
0664fc3b21 Update mud 2017-01-18 15:27:18 +00:00
Adrien Gallouët
2cb24c0523 Update mud 2017-01-16 16:11:18 +00:00
18 changed files with 343 additions and 112 deletions

View File

@@ -1,18 +0,0 @@
#!/bin/sh
export CC="gcc -static"
git clone https://github.com/jedisct1/libsodium --depth=1 --branch stable
cd libsodium || exit 1
./autogen.sh && ./configure --enable-minimal --disable-shared --prefix=/usr && make install
cd ..
./autogen.sh && ./configure && make
[ -x glorytun ] || exit 1
mkdir -p deploy
cp glorytun deploy/glorytun-$(cat VERSION)-$(uname -m).debug.bin
strip -s glorytun
cp glorytun deploy/glorytun-$(cat VERSION)-$(uname -m).bin

2
.gitignore vendored
View File

@@ -11,3 +11,5 @@ build-aux
.deps
.dirstamp
glorytun
build*
VERSION

View File

@@ -14,6 +14,8 @@ glorytun_SOURCES = \
src/option.h \
src/tun.c \
src/tun.h \
src/iface.c \
src/iface.h \
src/db.c \
src/db.h

View File

@@ -1,18 +1,53 @@
# π₁(Glorytun)=0
# Glorytun
Small, Simple and Stupid VPN over [mud](https://github.com/angt/mud).
#### Build and Install
### Build and Install
Glorytun depends on [libsodium](https://github.com/jedisct1/libsodium) version >= 1.0.4.
To build and install the latest version:
On Ubuntu, the following command should be sufficient:
$ git clone https://github.com/angt/glorytun --recursive --branch mud
$ sudo apt-get install meson libsodium-dev pkg-config
Grab the latest release from github:
$ git clone https://github.com/angt/glorytun --recursive
$ cd glorytun
$ ./autogen.sh
$ ./configure
$ make
# make install
To build and install the latest version with [meson](http://mesonbuild.com):
$ meson build
$ sudo ninja -C build install
The more classical autotools suite is also available.
### Easy setup with systemd
Just call `glorytun-setup` and follow the instructions.
Fist, setup the server:
$ sudo glorytun-setup
Config filename (tun0):
Server ip (enter for server conf):
Server key (enter to generate a new one):
Your new key: NEW_KEY
Start glorytun now ? (enter to skip): y
Copy the new generated key and use it when configuring the client:
$ sudo glorytun-setup
Config filename (tun0):
Server ip (enter for server conf): SERVER_IP
Server key (enter to generate a new one): NEW_KEY
Start glorytun now ? (enter to skip): y
You can check easily if it works by looking at your public ip.
To stop the service:
$ sudo systemctl stop glorytun@tun0
---
For feature requests and bug reports, please create an [issue](https://github.com/angt/glorytun/issues).

49
meson.build Normal file
View File

@@ -0,0 +1,49 @@
project('glorytun', 'c',
version: run_command('./version.sh').stdout(),
license: 'BSD-3-Clause',
default_options : [ 'buildtype=debugoptimized' ]
)
prefix = get_option('prefix')
bindir = join_paths(prefix, get_option('bindir'))
conf_data = configuration_data()
conf_data.set('prefix', prefix)
conf_data.set('bindir', bindir)
add_global_arguments('-DPACKAGE_VERSION="'+meson.project_version()+'"', language : 'c')
src = [
'src/common.c',
'src/iface.c',
'src/option.c',
'src/tun.c',
'mud/mud.c',
'src/main.c'
]
deps = [
dependency('libsodium', version : '>=1.0.4')
]
executable('glorytun', install: true, sources: src, dependencies: deps)
systemd = dependency('systemd', required: false)
if systemd.found()
systemdutildir = systemd.get_pkgconfig_variable('systemdutildir')
configure_file(
input: 'systemd/glorytun@.service.in',
output: 'glorytun@.service',
configuration: conf_data,
install_dir: join_paths(systemdutildir, 'system')
)
install_data('systemd/glorytun.network',
install_dir: join_paths(systemdutildir, 'network'))
install_data('systemd/glorytun-client.network',
install_dir: join_paths(systemdutildir, 'network'))
install_data('systemd/glorytun-run',
install_dir: bindir)
install_data('systemd/glorytun-setup',
install_dir: bindir)
endif

2
mud

Submodule mud updated: 19e3115420...13cf44c813

View File

@@ -26,23 +26,6 @@ gt_log(const char *fmt, ...)
va_end(ap);
}
void
gt_fatal(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
exit(EXIT_FAILURE);
}
void
gt_na(const char *name)
{
gt_log("%s is not available on your platform\n", name);
}
int
gt_tohex(char *dst, size_t dst_size, const uint8_t *src, size_t src_size)
{

View File

@@ -37,8 +37,6 @@
int gt_print (const char *, ...) _printf_(1,2);
void gt_log (const char *, ...) _printf_(1,2);
void gt_fatal (const char *, ...) _printf_(1,2) _noreturn_;
void gt_na (const char *);
int gt_tohex (char *, size_t, const uint8_t *, size_t);
int gt_fromhex (uint8_t *, size_t, const char *, size_t);

29
src/iface.c Normal file
View File

@@ -0,0 +1,29 @@
#include "common.h"
#include "str.h"
#include <sys/ioctl.h>
#include <net/if.h>
int
iface_set_mtu(char *dev_name, int mtu)
{
struct ifreq ifr = {
.ifr_mtu = mtu,
};
str_cpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1)
return -1;
int ret = ioctl(fd, SIOCSIFMTU, &ifr);
int err = errno;
close(fd);
errno = err;
return ret;
}

3
src/iface.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
int iface_set_mtu (char *, int);

View File

@@ -5,6 +5,7 @@
#include "option.h"
#include "str.h"
#include "tun.h"
#include "iface.h"
#include <fcntl.h>
#include <inttypes.h>
@@ -14,6 +15,7 @@
#include <stdio.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
@@ -24,10 +26,15 @@
#define O_CLOEXEC 0
#endif
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "unknown"
#endif
#define GT_MTU(X) ((X)-28)
static struct {
volatile sig_atomic_t quit;
volatile sig_atomic_t reload;
char *dev;
char *keyfile;
char *host;
@@ -45,6 +52,12 @@ static struct {
int mtu_auto;
int chacha20;
int version;
int keygen;
int persist;
struct {
unsigned char *data;
long size;
} buf;
} gt = {
.port = 5000,
.bind = {
@@ -56,6 +69,9 @@ static struct {
#ifdef __linux__
.ipv6 = 1,
#endif
.buf = {
.size = 64 * 1024,
},
};
static void
@@ -80,6 +96,7 @@ fd_set_nonblock(int fd)
static void
gt_quit_handler(int sig)
{
gt.reload = (sig == SIGHUP);
gt.quit = 1;
}
@@ -96,9 +113,9 @@ gt_set_signal(void)
sigaction(SIGINT, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
sa.sa_handler = SIG_IGN;
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGPIPE, &sa, NULL);
sigaction(SIGUSR1, &sa, NULL);
sigaction(SIGUSR2, &sa, NULL);
@@ -116,7 +133,7 @@ gt_print_secretkey(struct mud *mud)
char buf[2 * sizeof(key) + 1];
gt_tohex(buf, sizeof(buf), key, size);
gt_print("secret key: %s\n", buf);
gt_print("%s\n", buf);
}
static int
@@ -178,14 +195,17 @@ gt_setup_option(int argc, char **argv)
{ "bind-backup", &gt.bind.backup, option_str },
{ "bind-port", &gt.bind.port, option_long },
{ "dev", &gt.dev, option_str },
{ "persist", NULL, option_option },
{ "mtu", &gt.mtu, option_long },
{ "mtu-auto", NULL, option_option },
{ "keyfile", &gt.keyfile, option_str },
{ "keygen", NULL, option_option },
{ "timeout", &gt.timeout, option_long },
{ "time-tolerance", &gt.time_tolerance, option_long },
{ "v4only", NULL, option_option },
{ "v6only", NULL, option_option },
{ "chacha20", NULL, option_option },
{ "buf-size", &gt.buf.size, option_long },
{ "version", NULL, option_option },
{ NULL },
};
@@ -203,13 +223,13 @@ gt_setup_option(int argc, char **argv)
return 1;
}
if (gt.host && !option_is_set(opts, "keyfile")) {
gt_log("keyfile option must be set\n");
if ((int)gt.timeout <= 0) {
gt_log("bad timeout\n");
return 1;
}
if ((int)gt.timeout <= 0) {
gt_log("bad timeout\n");
if (gt.buf.size <= 0) {
gt_log("bad buf-size\n");
return 1;
}
@@ -226,6 +246,10 @@ gt_setup_option(int argc, char **argv)
gt.mtu_auto = option_is_set(opts, "mtu-auto");
gt.chacha20 = option_is_set(opts, "chacha20");
gt.version = option_is_set(opts, "version");
gt.keygen = option_is_set(opts, "keygen");
gt.persist = option_is_set(opts, "persist");
gt.buf.data = malloc(gt.buf.size);
return 0;
}
@@ -242,7 +266,7 @@ gt_setup_mtu(struct mud *mud, char *tun_name)
gt_log("setup MTU to %i on interface %s\n", mtu, tun_name);
if (tun_set_mtu(tun_name, mtu) == -1)
if (iface_set_mtu(tun_name, mtu) == -1)
perror("tun_set_mtu");
}
@@ -255,7 +279,7 @@ main(int argc, char **argv)
return 1;
if (gt.version) {
gt_print(PACKAGE_STRING "\n");
gt_print(PACKAGE_VERSION "\n");
return 0;
}
@@ -268,6 +292,36 @@ main(int argc, char **argv)
gt_log("couldn't create ICMP socket\n");
}
struct mud *mud = mud_create(gt.bind.port, gt.ipv4, gt.ipv6);
if (!mud) {
gt_log("couldn't create mud\n");
return 1;
}
if (gt.keygen || str_empty(gt.keyfile)) {
if (mud_new_key(mud)) {
gt_log("couldn't generate a new key\n");
return 1;
}
}
if (gt.keygen) {
gt_print_secretkey(mud);
return 0;
}
if (!gt.chacha20 && mud_set_aes(mud))
gt_log("AES is not available\n");
if (gt.timeout > 0)
mud_set_send_timeout_msec(mud, gt.timeout);
if (gt.time_tolerance > 0)
mud_set_time_tolerance_sec(mud, gt.time_tolerance);
mud_set_mtu(mud, GT_MTU(gt.mtu));
char *tun_name = NULL;
int tun_fd = tun_create(gt.dev, &tun_name);
@@ -277,26 +331,17 @@ main(int argc, char **argv)
return 1;
}
struct mud *mud = mud_create(gt.bind.port, gt.ipv4, gt.ipv6,
!gt.chacha20, GT_MTU(gt.mtu));
if (!mud) {
gt_log("couldn't create mud\n");
return 1;
}
if (tun_set_persist(tun_fd, gt.persist) == -1)
perror("tun_set_persist");
if (str_empty(gt.keyfile)) {
gt_print("here is your new secret key:\n");
gt_print_secretkey(mud);
} else {
if (gt_setup_secretkey(mud, gt.keyfile))
return 1;
}
mud_set_send_timeout_msec(mud, gt.timeout);
if (gt.time_tolerance > 0)
mud_set_time_tolerance_sec(mud, gt.time_tolerance);
if (gt.host && gt.port) {
if (gt.bind.backup) {
if (mud_peer(mud, gt.bind.backup, gt.host, gt.port, 1)) {
@@ -345,8 +390,6 @@ main(int argc, char **argv)
fd_set rfds;
FD_ZERO(&rfds);
unsigned char buf[8 * 1024];
int last_fd = 1 + MAX(tun_fd, MAX(mud_fd, icmp_fd));
while (!gt.quit) {
@@ -366,12 +409,12 @@ main(int argc, char **argv)
if (icmp_fd != -1 && FD_ISSET(icmp_fd, &rfds)) {
struct sockaddr_storage ss;
socklen_t sl = sizeof(ss);
ssize_t r = recvfrom(icmp_fd, buf, sizeof(buf), 0,
ssize_t r = recvfrom(icmp_fd, gt.buf.data, gt.buf.size, 0,
(struct sockaddr *)&ss, &sl);
if (r >= 8) {
struct ip_common ic;
if (!ip_get_common(&ic, buf, r) && ic.proto == 1) {
unsigned char *data = &buf[ic.hdr_size];
if (!ip_get_common(&ic, gt.buf.data, r) && ic.proto == 1) {
unsigned char *data = &gt.buf.data[ic.hdr_size];
if (data[0] == 3) {
int mtu = (data[6] << 8) | data[7];
if (mtu) {
@@ -386,15 +429,15 @@ main(int argc, char **argv)
if (FD_ISSET(tun_fd, &rfds)) {
size_t size = 0;
while (sizeof(buf) - size >= gt.mtu) {
const int r = tun_read(tun_fd, &buf[size], sizeof(buf) - size);
while (gt.buf.size - size >= gt.mtu) {
const int r = tun_read(tun_fd, &gt.buf.data[size], gt.buf.size - size);
if (r <= 0 || r > gt.mtu)
break;
struct ip_common ic;
if (ip_get_common(&ic, &buf[size], r) || ic.size != r)
if (ip_get_common(&ic, &gt.buf.data[size], r) || ic.size != r)
break;
size += r;
@@ -409,7 +452,7 @@ main(int argc, char **argv)
while (q < size) {
struct ip_common ic;
if ((ip_get_common(&ic, &buf[q], size - q)) ||
if ((ip_get_common(&ic, &gt.buf.data[q], size - q)) ||
(ic.size > size - q))
break;
@@ -425,7 +468,7 @@ main(int argc, char **argv)
if (p >= q)
break;
int r = mud_send(mud, &buf[p], q - p, tc);
int r = mud_send(mud, &gt.buf.data[p], q - p, tc);
if (r == -1 && errno == EMSGSIZE) {
gt_setup_mtu(mud, tun_name);
@@ -439,30 +482,39 @@ main(int argc, char **argv)
}
if (FD_ISSET(mud_fd, &rfds)) {
while (1) {
const int size = mud_recv(mud, buf, sizeof(buf));
size_t size = 0;
if (size <= 0) {
if (size == -1 && errno != EAGAIN)
while (gt.buf.size - size >= gt.mtu) {
const int r = mud_recv(mud, &gt.buf.data[size], gt.buf.size - size);
if (r <= 0) {
if (r == -1 && errno != EAGAIN)
perror("mud_recv");
break;
}
size += r;
}
int p = 0;
while (p < size) {
struct ip_common ic;
if ((ip_get_common(&ic, &buf[p], size - p)) ||
if ((ip_get_common(&ic, &gt.buf.data[p], size - p)) ||
(ic.size > size - p))
break;
tun_write(tun_fd, &buf[p], ic.size);
tun_write(tun_fd, &gt.buf.data[p], ic.size);
p += ic.size;
}
}
}
if (gt.reload && tun_fd >= 0) {
if (tun_set_persist(tun_fd, 1) == -1)
perror("tun_set_persist");
}
return 0;

View File

@@ -17,6 +17,7 @@
#define IFF_TUN 0x0001
#define IFF_NO_PI 0x1000
#define TUNSETIFF _IOW('T', 202, int)
#define TUNSETPERSIST _IOW('T', 203, int)
#endif
#ifdef __APPLE__
@@ -239,24 +240,12 @@ tun_write(int fd, const void *data, size_t size)
}
int
tun_set_mtu(char *dev_name, int mtu)
tun_set_persist(int fd, int on)
{
struct ifreq ifr = {
.ifr_mtu = mtu,
};
str_cpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1)
#ifdef TUNSETPERSIST
return ioctl(fd, TUNSETPERSIST, on);
#else
errno = ENOSYS;
return -1;
int ret = ioctl(fd, SIOCSIFMTU, &ifr);
int err = errno;
close(fd);
errno = err;
return ret;
#endif
}

View File

@@ -3,4 +3,4 @@
int tun_create (char *, char **);
int tun_read (int, void *, size_t);
int tun_write (int, const void *, size_t);
int tun_set_mtu (char *, int);
int tun_set_persist (int, int);

View File

@@ -0,0 +1,10 @@
[Match]
Name=gtc-*
[Network]
Description=Glorytun client device
DHCP=ipv4
[DHCP]
CriticalConnection=yes
RouteTable=200

29
systemd/glorytun-run Executable file
View File

@@ -0,0 +1,29 @@
#!/bin/sh
if [ ! -f "$1" ]; then
echo "usage: $(basename "$0") FILE"
exit 1
fi
. "$(readlink -f "$1")"
DEV="gt${HOST:+c}-$(basename "$1")"
# Setting BIND is like going to 'expert mode'
# This helper is pretty stupid and still needs some work
if [ -n "$HOST" ] && [ -z "$BIND" ]; then
BIND=$(ip route get "$HOST" | awk '/src/{getline;print $0}' RS=' ')
ip rule add from "$BIND" table main pref 32000
ip rule add from all table 200 pref 32001
fi
exec glorytun \
v4only \
keyfile "$1".key \
dev "$DEV" \
${HOST:+host "$HOST"} \
${PORT:+port "$PORT"} \
${BIND:+bind "$BIND"} \
${BIND_PORT:+bind-port "$BIND_PORT"} \
${MTU:+mtu "$MTU"} \
${MTU_AUTO:+mtu-auto}

42
systemd/glorytun-setup Executable file
View File

@@ -0,0 +1,42 @@
#!/bin/sh
set -e
_ask() {
printf "%s: " "$1"
read -r "$2"
}
_NAME=tun0
_ask "Config filename ($_NAME)" NAME
NAME=${NAME:-$_NAME}
if [ -f /etc/glorytun/"$NAME" ]; then
echo "This config already exit!"
exit 1
fi
_ask "Server ip (enter for server conf)" HOST
_ask "Server key (enter to generate a new one)" KEY
if [ -z "$KEY" ]; then
KEY=$(glorytun keygen) || exit
echo "Your new key: $KEY"
fi
mkdir -p /etc/glorytun
FILE="/etc/glorytun/$NAME"
echo "${HOST:+HOST=$HOST}" > "$FILE"
touch "$FILE.key"
chmod 600 "$FILE.key"
echo "$KEY" > "$FILE.key"
_ask "Start glorytun now ? (enter to skip)" START
case "$START" in
y*|Y*)
systemctl restart systemd-networkd
systemctl start glorytun@"$NAME"
;;
esac

14
systemd/glorytun.network Normal file
View File

@@ -0,0 +1,14 @@
[Match]
Name=gt-*
[Network]
Description=Glorytun server device
Address=0.0.0.0/24
DHCPServer=yes
IPMasquerade=yes
[DHCPServer]
PoolOffset=2
PoolSize=1
EmitDNS=yes
DNS=9.9.9.9

View File

@@ -0,0 +1,12 @@
[Unit]
Description=Glorytun on %I
After=network.target
[Service]
Type=simple
Restart=always
ExecStart=@bindir@/glorytun-run /etc/glorytun/%i
CapabilityBoundingSet=CAP_NET_ADMIN
[Install]
WantedBy=multi-user.target