Compare commits

...

106 Commits

Author SHA1 Message Date
Adrien Gallouët
db718d5942 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-04-03 10:00:59 +00:00
Adrien Gallouët
3da880f5c5 Use -fstack-protector-strong
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-04-03 09:38:53 +00:00
Adrien Gallouët
86fe69d644 Fix conversion in src/bind.c
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-04-03 09:33:07 +00:00
Adrien Gallouët
5c29753343 Fix conversion in src/bench.c
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-04-03 09:30:54 +00:00
Adrien Gallouët
70bc9cc205 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-04-03 09:25:42 +00:00
Adrien Gallouët
5c3ec8e264 Update argz
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-04-03 09:10:21 +00:00
Adrien Gallouët
6496adcd91 Cleanup Makefile
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-04-02 15:52:28 +00:00
Adrien Gallouët
4ec2079e22 Always use size_t for MTU
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-04-02 14:41:33 +00:00
Adrien Gallouët
f4611efbb2 Fix conversion in src/path.c
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-04-02 14:41:33 +00:00
Adrien Gallouët
d703a66988 Compute sun_path from PID
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-04-02 14:15:13 +00:00
Adrien Gallouët
568eeee70b Fix conversion in src/common.c
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-04-02 14:15:13 +00:00
Adrien Gallouët
6e6c72746f Fix conversion in src/tun.c
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-04-02 14:15:02 +00:00
Adrien Gallouët
cd2ee2a7af Fix conversion in src/ip.h
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-04-02 14:14:47 +00:00
Adrien Gallouët
e338626c46 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-04-01 15:38:07 +00:00
Adrien Gallouët
71aedce8b2 Ask for a non pedantic c11 compiler 2019-04-01 13:16:29 +00:00
Adrien Gallouët
9c8e043053 Add a stupid untracked Makefile 2019-04-01 07:48:55 +00:00
Adrien Gallouët
871f488097 Remove old sync command
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-03-09 15:07:18 +00:00
Adrien Gallouët
159104ce9c Don't wake up without paths
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-03-09 14:39:22 +00:00
Adrien Gallouët
0dddca3b61 Update LICENSE --recursive
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-03-05 21:59:37 +00:00
Adrien Gallouët
cbae4f5a30 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-03-05 11:06:43 +00:00
Adrien Gallouët
61db08063c Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-02-22 09:16:15 +00:00
Adrien Gallouët
dec3151fd2 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-02-17 20:21:02 +00:00
Adrien Gallouët
a36f1d5354 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-02-15 22:05:24 +00:00
Adrien Gallouët
ae713a2197 Update argz
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-02-15 22:01:02 +00:00
Adrien Gallouët
6555cd98d5 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-02-15 19:37:35 +00:00
Adrien Gallouët
bde9e6e59a Remove sync option
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-02-13 17:05:40 +00:00
Adrien Gallouët
9a8d95399d Fix typo
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-02-12 18:04:28 +00:00
Adrien Gallouët
324ba6d525 Update README.md and glorytun-setup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-02-12 11:10:55 +00:00
Adrien Gallouët
b91788080f Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-02-10 21:17:15 +00:00
Adrien Gallouët
a65cb2ad15 Add option path rate tx/rx
These two options are mandatory since dynamic shapping
is disabled for now.

Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-02-09 16:22:11 +00:00
Adrien Gallouët
9131af6e85 2019
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-01-02 15:53:12 +00:00
Adrien Gallouët
5fca6bcab1 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2019-01-02 15:52:05 +00:00
Adrien Gallouët
067ddd4aa0 Ignore dirty
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-12-05 09:11:59 +00:00
Adrien Gallouët
3d184721ab Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-12-05 09:02:17 +00:00
Adrien Gallouët
20d589fa70 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-12-05 08:56:31 +00:00
Adrien Gallouët
adb825020a Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-12-05 08:56:19 +00:00
Adrien Gallouët
e14045ffa2 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-12-02 09:34:05 +00:00
Adrien Gallouët
4d5ae60844 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-12-01 15:05:52 +00:00
Adrien Gallouët
5b64c697ea Remove option timeout
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-12-01 14:56:03 +00:00
Adrien Gallouët
b4f796469f Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-12-01 11:48:37 +00:00
Adrien Gallouët
0e052dc2db Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-11-29 22:24:32 +00:00
Adrien Gallouët
8ff9d3d7a1 Force version.sh to check only local .git
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-11-22 14:19:41 +00:00
Adrien Gallouët
6bcc46c757 Update mud and show status in path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-11-08 17:47:00 +00:00
Adrien Gallouët
3898afd524 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-11-05 11:44:02 +00:00
Adrien Gallouët
f20fff0e87 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-10-21 08:56:14 +00:00
Adrien Gallouët
9e1001fa17 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-10-21 08:52:42 +00:00
Adrien Gallouët
9957581e60 Don't use crypto_shorthash_keygen()
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-10-02 16:14:44 +00:00
Adrien Gallouët
61176d4f47 Fix BSD
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-10-01 15:31:14 +00:00
Adrien Gallouët
e8bda24ec0 Fix ip.h
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-10-01 07:19:30 +00:00
Adrien Gallouët
5c9cbfc952 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-10-01 07:04:32 +00:00
Adrien Gallouët
13c905d725 Cleanup ip.h
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-10-01 06:57:15 +00:00
Adrien Gallouët
56a3a751db Use siphash to select path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-09-29 16:13:01 +00:00
Adrien Gallouët
6719b19681 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-09-24 13:00:09 +00:00
Adrien Gallouët
310513c569 Don't log useless things in the main loop
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-08-17 14:22:34 +00:00
Adrien Gallouët
a0bdb56441 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-08-16 13:01:14 +00:00
Adrien Gallouët
c15343f8f6 Commands show and path now support pipe output
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-06-15 17:57:09 +00:00
Adrien Gallouët
41f66e55bc Use mud_sync()
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-06-15 10:06:51 +00:00
Adrien Gallouët
9c7f98a823 Add option sync to command bind
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-06-07 16:57:02 +00:00
Adrien Gallouët
da350aff9c Add option timeout in command sync
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-06-03 18:02:34 +00:00
Adrien Gallouët
c7fed357fb Improve exit codes for scripts
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-06-02 15:43:08 +00:00
Adrien Gallouët
524ae42069 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-06-02 08:26:09 +00:00
Adrien Gallouët
2dbf5fb765 Add the sync command
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-21 09:26:37 +00:00
Adrien Gallouët
a3bb488fd5 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-16 22:07:13 +00:00
Adrien Gallouët
022e478fb9 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-16 21:41:39 +00:00
Adrien Gallouët
f3b44e2f45 Option bufsize is no longer useful
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-15 06:48:02 +00:00
Adrien Gallouët
23b7aeb68f Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-15 06:44:55 +00:00
Adrien Gallouët
1e2004c7dd Ask for a keyfile
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-15 06:42:51 +00:00
Adrien Gallouët
e12d136ba3 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-14 13:11:20 +00:00
Adrien Gallouët
ca96be5fe5 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-11 16:55:44 +00:00
Adrien Gallouët
d0a9c69f7c Update argz
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-11 16:51:05 +00:00
Adrien Gallouët
3ffce5da1b Add a compatibility note in the README
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-10 20:24:14 +00:00
Adrien Gallouët
aeb33342a4 Remove useless mtu log
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-10 19:53:06 +00:00
Adrien Gallouët
ca71508e5c Show pid
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-10 19:51:18 +00:00
Adrien Gallouët
36be8008d8 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-10 14:05:34 +00:00
Adrien Gallouët
be17650555 Not using ICMP Next-hop MTU is a feature
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-10 13:49:42 +00:00
Adrien Gallouët
873efb4f82 Show help when no arguments
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-10 13:48:20 +00:00
Adrien Gallouët
357d5a0859 Update README.md
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-10 10:22:16 +00:00
Adrien Gallouët
5c532b2e56 Be more verbose
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-09 15:27:57 +00:00
Adrien Gallouët
0cce48e9fd Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-05 19:35:42 +00:00
Adrien Gallouët
ee9ed7e3a6 Use full hash as version if no tags
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-05 13:17:55 +00:00
Adrien Gallouët
841c2afed0 Update mud (new proto)
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-05-05 12:57:49 +00:00
Adrien Gallouët
60a5b3e00a Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-26 20:25:49 +00:00
Adrien Gallouët
e243d8371a Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-26 05:40:21 +00:00
Adrien Gallouët
767aff211f Update mud (bw probing)
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-25 09:10:37 +00:00
Adrien Gallouët
eb04190c58 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-23 20:54:34 +00:00
Adrien Gallouët
d25957b108 Show latency-smoothed maxrate per path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-21 12:29:02 +00:00
Adrien Gallouët
a5f634ee28 Show rate per path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-18 16:37:20 +00:00
Adrien Gallouët
1736b6e043 Show rttvar per path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-06 16:46:55 +00:00
Adrien Gallouët
8401b7c112 Show number of packets per path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-04-03 09:49:00 +00:00
Adrien Gallouët
7276305906 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-26 13:22:46 +00:00
Adrien Gallouët
6e75f4282d Don't forget BSD..
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-19 09:53:43 +00:00
Adrien Gallouët
7999344c39 Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-19 09:38:18 +00:00
Adrien Gallouët
7a9f6fc8b8 Remove old packet aggregation
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-17 13:21:16 +00:00
Adrien Gallouët
dabd16e4b4 Improve output of show/path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-16 21:15:10 +00:00
Adrien Gallouët
1698a08b08 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-15 22:07:48 +00:00
Adrien Gallouët
4646cbb15e Code cleanup
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-15 22:07:12 +00:00
Adrien Gallouët
c2bd415382 Sanitize memory
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-15 22:06:23 +00:00
Adrien Gallouët
245b8e671e Fix ctl_connect()
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-15 22:05:42 +00:00
Adrien Gallouët
c06abdbe3c Add set option kxtimeout
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-14 07:57:32 +00:00
Adrien Gallouët
b0a589b792 Use GT_RUNDIR for local sockets
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-14 07:06:25 +00:00
Adrien Gallouët
66cdcf2ee3 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-14 06:55:37 +00:00
Adrien Gallouët
7c50a9d162 Show public ip and port for each path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-10 15:33:18 +00:00
Adrien Gallouët
6538d301d1 Show mtu for each path
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-09 23:17:10 +00:00
Adrien Gallouët
63831d6efc Update mud and path_status
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-09 23:16:13 +00:00
Adrien Gallouët
cbb498bb74 Update mud
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-06 16:04:04 +00:00
Adrien Gallouët
e2706aecdb Set errno when gt_toaddr() fails
Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
2018-03-06 16:03:25 +00:00
23 changed files with 541 additions and 343 deletions

2
.gitmodules vendored
View File

@@ -1,6 +1,8 @@
[submodule "mud"]
path = mud
url = https://github.com/angt/mud.git
ignore = dirty
[submodule "argz"]
path = argz
url = https://github.com/angt/argz.git
ignore = dirty

View File

@@ -1,4 +1,4 @@
Copyright (c) 2015-2016, angt
Copyright (c) 2015-2019, Adrien Gallouët <adrien@gallouet.fr>
All rights reserved.
Redistribution and use in source and binary forms, with or without

32
Makefile Normal file
View File

@@ -0,0 +1,32 @@
NAME := glorytun
VERSION := $(shell ./version.sh)
DIST := $(NAME)-$(VERSION)
DESTDIR ?=
CC ?= gcc
INSTALL ?= install
prefix ?= /usr
CFLAGS ?= -std=c11 -O2 -Wall -fstack-protector-strong
FLAGS := $(CFLAGS) $(LDFLAGS) $(CPPFLAGS)
FLAGS += -DPACKAGE_NAME=\"$(NAME)\" -DPACKAGE_VERSION=\"$(VERSION)\"
SRC := argz/argz.c mud/mud.c $(wildcard src/*.c)
.PHONY: $(NAME)
$(NAME):
@echo "Building $(NAME)"
@$(CC) $(FLAGS) -o $(NAME) $(SRC) -lsodium -lm
.PHONY: install
install: $(NAME)
@echo "Installing $(NAME)"
@$(INSTALL) -m 755 -d $(DESTDIR)$(prefix)/bin
@$(INSTALL) -m 755 -s $(NAME) $(DESTDIR)$(prefix)/bin
.PHONY: dist
dist:
@echo "Building $(DIST).tar.gz"
@(git --git-dir=.git ls-files --recurse-submodules -- ':!:.*' ':!:**/.*' && echo VERSION) | ( \
tar zcf $(DIST).tar.gz -T- --transform 's:^:$(DIST)/:' || \
tar zcf $(DIST).tar.gz -T- -s ':^:$(DIST)/:' ) 2>/dev/null

138
README.md
View File

@@ -1,54 +1,132 @@
# Glorytun
Small, Simple and Stupid VPN over [mud](https://github.com/angt/mud).
Glorytun is a small, simple and secure VPN over [mud](https://github.com/angt/mud).
### Build and Install
## Compatibility
Glorytun depends on [libsodium](https://github.com/jedisct1/libsodium) version >= 1.0.4.
Glorytun only depends on [libsodium](https://github.com/jedisct1/libsodium) version >= 1.0.4.
Which can be installed on a wide variety of systems.
On Ubuntu, the following command should be sufficient:
Linux is the platform of choice but the code is standard so it should be easily ported on other posix systems.
It was successfully tested on OpenBSD, FreeBSD and MacOS.
$ sudo apt-get install meson libsodium-dev pkg-config
IPv4 and IPv6 are supported.
Grab the latest release from github:
## Features
The key features of Glorytun come directly from mud:
* **Fast and highly secure**
The use of UDP and [libsodium](https://github.com/jedisct1/libsodium) allows you to secure
your communications without impacting performance.
Glorytun uses AES only if AES-NI is available otherwise ChaCha20 is used.
If you are not cpu bounded, you can force the use of ChaCha20 for higher security.
All messages are encrypted, authenticated and marked with a timestamp.
Perfect forward secrecy is also implemented with ECDH over Curve25519.
* **Multipath and active failover**
This is the main feature of Glorytun that allows to build an SD-WAN like service.
This allows a TCP connection to explore and exploit multiple links without being disconnected.
Aggregation should work on all conventional links, only very high latency (+500ms) links are not recommended for now.
* **Traffic shaping**
Shaping is very important in network, it allows to keep a low latency without sacrificing the bandwidth.
It also helps the multipath scheduler to make better decisions.
Currently it must be configured by hand, but soon Glorytun will do it for you.
* **Path MTU discovery without ICMP**
Bad MTU configuration is a very common problem in the world of VPN.
As it is critical, Glorytun will try to setup it correctly by guessing its value.
It doesn't rely on ICMP Next-hop MTU to avoid black holes.
In asymmetric situations the minimum MTU is selected.
## Caveats
Glorytun is strongly secure by default and protects against replay attacks,
the clock between the client and the server must be synchronized.
By default, an offset of 10min is accepted.
## Build and Install
You will need `git`, `make`, `gcc` and `libsodium`:
$ sudo apt install git make gcc libsodium-dev # debian based
$ sudo yum install git make gcc libsodium-devel # redhat based
To build and install the latest release from github:
$ git clone https://github.com/angt/glorytun --recursive
$ cd glorytun
$ sudo make install
To build and install the latest version with [meson](http://mesonbuild.com):
$ meson build
$ sudo ninja -C build install
This will install the binary in `/usr/bin` by default.
The more classical autotools suite is also available.
### Easy setup with systemd
## Usage
Just call `glorytun-setup` and follow the instructions.
Just run `glorytun` with no arguments to view the list of available commands:
First, setup the server:
```
$ glorytun
available commands:
$ sudo glorytun-setup
Config filename (tun0):
Server ip (enter for server conf):
Bind to port (5000):
Server key (enter to generate a new one):
Your new key: NEW_KEY
Start glorytun now ? (enter to skip): y
show show all running tunnels
bench start a crypto bench
bind start a new tunnel
set change tunnel properties
keygen generate a new secret key
path manage paths
version show version
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 port (5000):
Server key (enter to generate a new one): NEW_KEY
Start glorytun now ? (enter to skip): y
Use the keyword `help` after a command to show its usage.
You can check easily if it works by looking at your public ip.
To stop the service:
## Mini HowTo
$ sudo systemctl stop glorytun@tun0
Glorytun does not touch the configuration of its network interface (except for the MTU),
It is up to the user to do it according to the tools available
on his system (systemd-networkd, netifd, ...).
This also allows a wide variety of configurations.
To start a server:
# (umask 066; glorytun keygen > my_secret_key)
# glorytun bind 0.0.0.0 keyfile my_secret_key &
You should now have an unconfigured network interface (let's say `tun0`).
For example, the simplest setup with `ifconfig`:
# ifconfig tun0 10.0.1.1 pointopoint 10.0.1.2 up
To check if the server is running, simply call `glorytun show`.
It will show you all of the running tunnels.
To start a new client, you need to get the secret key generated for the server.
Then simply call:
# glorytun bind 0.0.0.0 to SERVER_IP keyfile my_secret_key &
# ifconfig tun0 10.0.1.2 pointopoint 10.0.1.1 up
Now you have to setup your path, let's say you have an ADSL link that can do 1Mbit upload and 20Mbit download then call:
# glorytun path up LOCAL_IPADDR rate tx 1mbit rx 20mbit
Again, to check if your path is working, you can watch its status with `glorytun path`.
You should now be able to ping your server with `ping 10.0.1.1`.
If you use systemd-networkd, you can easily setup your tunnels with the helper program `glorytun-setup`.
## Thanks
* @jedisct1 for all his help and the code for MacOS/BSD.
* The team OTB (@bessa, @gregdel, @pouulet, @sduponch and @simon) for all tests and discussions.
* OVH to support this soft :)
---

2
argz

Submodule argz updated: 2d6a6d635f...31f3c44d9b

View File

@@ -4,7 +4,6 @@ AC_INIT([glorytun],
[https://github.com/angt/glorytun/issues],
[glorytun],
[https://github.com/angt/glorytun])
AC_DEFINE_UNQUOTED([VERSION_MAJOR], [m4_esyscmd([./version.sh major])])
AC_CONFIG_SRCDIR([src/common.h])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])

2
mud

Submodule mud updated: b809bf0785...06e165e664

View File

@@ -27,11 +27,13 @@ gt_now(void)
#elif defined CLOCK_MONOTONIC
struct timespec tv;
clock_gettime(CLOCK_MONOTONIC, &tv);
return tv.tv_sec * 1000000ULL + tv.tv_nsec / 1000ULL;
return (unsigned long long)tv.tv_sec * 1000000ULL
+ (unsigned long long)tv.tv_nsec / 1000ULL;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000000ULL + tv.tv_usec;
return (unsigned long long)tv.tv_sec * 1000000ULL
+ (unsigned long long)tv.tv_usec;
#endif
}
@@ -105,7 +107,7 @@ gt_bench(int argc, char **argv)
double mbps_max = 0.0;
double mbps_dlt = INFINITY;
while (!gt_quit && mbps_dlt > ldexp(mbps, -precision)) {
while (!gt_quit && mbps_dlt > ldexp(mbps, -(int)precision)) {
crypto_aead_aes256gcm_state ctx;
if (!chacha)
@@ -116,7 +118,7 @@ gt_bench(int argc, char **argv)
size_t bytes = 0;
gt_alarm = 0;
alarm(duration);
alarm((unsigned int)duration);
while (!gt_quit && !gt_alarm) {
if (chacha) {
@@ -133,7 +135,7 @@ gt_bench(int argc, char **argv)
total_dt += gt_now() - now;
total_bytes += bytes;
mbps = (total_bytes * 8.0) / total_dt;
mbps = ((double)total_bytes * 8.0) / (double)total_dt;
mbps_min = fmin(mbps_min, mbps);
mbps_max = fmax(mbps_max, mbps);
mbps_dlt = fabs(mbps_old - mbps);

View File

@@ -12,6 +12,8 @@
#include "../argz/argz.h"
#include "../mud/mud.h"
#include <sodium.h>
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
@@ -65,7 +67,7 @@ gt_setup_secretkey(struct mud *mud, const char *keyfile)
break;
}
size += r;
size += (size_t)r;
}
close(fd);
@@ -86,21 +88,16 @@ gt_setup_secretkey(struct mud *mud, const char *keyfile)
}
static size_t
gt_setup_mtu(struct mud *mud, const char *tun_name)
gt_setup_mtu(struct mud *mud, size_t old, const char *tun_name)
{
static size_t oldmtu = 0;
size_t mtu = mud_get_mtu(mud);
if (mtu == oldmtu)
if (mtu == old)
return mtu;
gt_log("setup MTU to %zu on interface %s\n", mtu, tun_name);
if (iface_set_mtu(tun_name, mtu) == -1)
perror("tun_set_mtu");
oldmtu = mtu;
return mtu;
}
@@ -113,8 +110,6 @@ gt_bind(int argc, char **argv)
unsigned short peer_port = bind_port;
const char *dev = NULL;
const char *keyfile = NULL;
size_t bufsize = 64 * 1024 * 1024;
size_t mtu = 1330;
struct argz toz[] = {
{NULL, "IPADDR", &peer_addr, argz_addr},
@@ -126,61 +121,58 @@ gt_bind(int argc, char **argv)
{NULL, "PORT", &bind_port, argz_ushort},
{"to", NULL, &toz, argz_option},
{"dev", "NAME", &dev, argz_str},
{"mtu", "BYTES", &mtu, argz_bytes},
{"keyfile", "FILE", &keyfile, argz_str},
{"chacha", NULL, NULL, argz_option},
{"persist", NULL, NULL, argz_option},
{"bufsize", "BYTES", &bufsize, argz_bytes},
{NULL}};
if (argz(bindz, argc, argv))
return 1;
gt_set_port((struct sockaddr *)&bind_addr, bind_port);
gt_set_port((struct sockaddr *)&peer_addr, peer_port);
unsigned char *buf = malloc(bufsize);
if (!buf) {
perror("malloc");
if (str_empty(keyfile)) {
gt_log("a keyfile is needed!\n");
return 1;
}
gt_set_port((struct sockaddr *)&bind_addr, bind_port);
gt_set_port((struct sockaddr *)&peer_addr, peer_port);
int chacha = argz_is_set(bindz, "chacha");
int persist = argz_is_set(bindz, "persist");
struct mud *mud = mud_create((struct sockaddr *)&bind_addr);
if (sodium_init() == -1) {
gt_log("couldn't init sodium\n");
return 1;
}
if (!mud) {
unsigned char hashkey[crypto_shorthash_KEYBYTES];
randombytes_buf(hashkey, sizeof(hashkey));
struct mud *mud = mud_create((struct sockaddr *)&bind_addr);
const int mud_fd = mud_get_fd(mud);
if (mud_fd == -1) {
gt_log("couldn't create mud\n");
return 1;
}
if (str_empty(keyfile)) {
if (mud_set_key(mud, NULL, 0)) {
gt_log("couldn't generate a new key\n");
return 1;
}
} else {
if (gt_setup_secretkey(mud, keyfile))
return 1;
}
if (gt_setup_secretkey(mud, keyfile))
return 1;
if (!chacha && mud_set_aes(mud)) {
gt_log("AES is not available\n");
gt_log("AES is not available, enjoy ChaCha20!\n");
chacha = 1;
}
char tun_name[64];
int tun_fd = tun_create(tun_name, sizeof(tun_name) - 1, dev);
const int tun_fd = tun_create(tun_name, sizeof(tun_name) - 1, dev);
if (tun_fd == -1) {
gt_log("couldn't create tun device\n");
return 1;
}
mud_set_mtu(mud, mtu);
mtu = gt_setup_mtu(mud, tun_name);
size_t mtu = gt_setup_mtu(mud, 0, tun_name);
if (tun_set_persist(tun_fd, persist) == -1)
perror("tun_set_persist");
@@ -192,39 +184,56 @@ gt_bind(int argc, char **argv)
}
}
int ctl_fd = ctl_create("/run/" PACKAGE_NAME, tun_name);
const int ctl_fd = ctl_create(GT_RUNDIR, tun_name);
if (ctl_fd == -1) {
perror("ctl_create");
return 1;
}
int mud_fd = mud_get_fd(mud);
fd_set_nonblock(tun_fd);
fd_set_nonblock(mud_fd);
fd_set_nonblock(ctl_fd);
gt_log("running...\n");
const long pid = (long)getpid();
gt_log("running on device %s as pid %li\n", tun_name, pid);
fd_set rfds;
FD_ZERO(&rfds);
int last_fd = 1 + MAX(tun_fd, MAX(mud_fd, ctl_fd));
const int last_fd = 1 + MAX(tun_fd, MAX(mud_fd, ctl_fd));
unsigned char buf[4096];
while (!gt_quit) {
FD_SET(tun_fd, &rfds);
long send_wait = mud_send_wait(mud);
if (send_wait) {
FD_CLR(tun_fd, &rfds);
} else {
FD_SET(tun_fd, &rfds);
}
FD_SET(mud_fd, &rfds);
FD_SET(ctl_fd, &rfds);
if (select(last_fd, &rfds, NULL, NULL, NULL) == -1) {
if (errno != EBADF)
continue;
perror("select");
return 1;
struct timeval tv = {
.tv_sec = 0,
.tv_usec = send_wait,
};
const int ret = select(last_fd, &rfds, NULL, NULL, send_wait > 0 ? &tv : NULL);
if (ret == -1) {
if (errno == EBADF) {
perror("select");
break;
}
continue;
}
mtu = gt_setup_mtu(mud, tun_name);
mtu = gt_setup_mtu(mud, mtu, tun_name);
if (FD_ISSET(ctl_fd, &rfds)) {
struct ctl_msg req, res = {.reply = 1};
@@ -241,7 +250,8 @@ gt_bind(int argc, char **argv)
case CTL_NONE:
break;
case CTL_STATE:
if (mud_set_state(mud, (struct sockaddr *)&req.path.addr, req.path.state))
if (mud_set_state(mud, (struct sockaddr *)&req.path.addr,
req.path.state, req.path.rate_tx, req.path.rate_rx))
res.ret = errno;
break;
case CTL_PATH_STATUS:
@@ -257,33 +267,34 @@ gt_bind(int argc, char **argv)
res.ret = EAGAIN;
for (unsigned i = 0; i < count; i++) {
if (i && sendto(ctl_fd, &res, sizeof(res), 0,
(const struct sockaddr *)&ss, sl) == -1)
perror("sendto(ctl)");
memcpy(&res.path_status, &paths[i], sizeof(struct mud_path));
if (sendto(ctl_fd, &res, sizeof(res), 0,
(const struct sockaddr *)&ss, sl) == -1)
perror("sendto(ctl)");
}
free(paths);
res.ret = 0;
}
break;
case CTL_MTU:
mud_set_mtu(mud, (size_t)req.mtu);
mtu = gt_setup_mtu(mud, tun_name);
res.mtu = mtu;
mud_set_mtu(mud, req.mtu);
res.mtu = mtu = gt_setup_mtu(mud, mtu, tun_name);
break;
case CTL_TC:
if (mud_set_tc(mud, req.tc))
res.ret = errno;
break;
case CTL_TIMEOUT:
if (mud_set_send_timeout(mud, req.timeout))
case CTL_KXTIMEOUT:
if (mud_set_keyx_timeout(mud, req.ms))
res.ret = errno;
break;
case CTL_TIMETOLERANCE:
if (mud_set_time_tolerance(mud, req.timetolerance))
if (mud_set_time_tolerance(mud, req.ms))
res.ret = errno;
break;
case CTL_STATUS:
res.status.pid = pid;
res.status.mtu = mtu;
res.status.chacha = chacha;
res.status.bind = bind_addr;
@@ -298,89 +309,26 @@ gt_bind(int argc, char **argv)
}
}
if (FD_ISSET(tun_fd, &rfds)) {
size_t size = 0;
if (FD_ISSET(mud_fd, &rfds)) {
const int r = mud_recv(mud, buf, sizeof(buf));
while (bufsize - size >= mtu) {
const int r = tun_read(tun_fd, &buf[size], bufsize - size);
if (r <= 0 || r > mtu)
break;
struct ip_common ic;
if (ip_get_common(&ic, &buf[size], r) || ic.size != r)
break;
size += r;
}
size_t p = 0;
while (p < size) {
size_t q = p;
int tc = 0;
while (q < size) {
struct ip_common ic;
if ((ip_get_common(&ic, &buf[q], size - q)) ||
(ic.size > size - q))
break;
if (q + ic.size > p + mtu)
break;
q += ic.size;
if (tc < (ic.tc & 0xFC))
tc = ic.tc & 0xFC;
}
if (p >= q)
break;
int r = mud_send(mud, &buf[p], q - p, tc);
if (r == -1) {
if (errno == EMSGSIZE) {
mtu = gt_setup_mtu(mud, tun_name);
} else if (errno != EAGAIN) {
perror("mud_send");
}
}
p = q;
}
if (r > 0 && ip_is_valid(buf, r))
tun_write(tun_fd, buf, (size_t)r);
}
if (FD_ISSET(mud_fd, &rfds)) {
size_t size = 0;
if (FD_ISSET(tun_fd, &rfds) && !mud_send_wait(mud)) {
struct ip_common ic;
const int r = tun_read(tun_fd, buf, sizeof(buf));
while (bufsize - size >= mtu) {
const int r = mud_recv(mud, &buf[size], bufsize - size);
if (r > 0 && !ip_get_common(&ic, buf, r)) {
// TODO: disable hash for now
// unsigned char hash[crypto_shorthash_BYTES];
// crypto_shorthash(hash, (const unsigned char *)&ic, sizeof(ic), hashkey);
if (r <= 0) {
if (r == -1 && errno != EAGAIN)
perror("mud_recv");
break;
}
unsigned h = 0;
// memcpy(&h, hash, sizeof(h));
size += r;
}
size_t p = 0;
while (p < size) {
struct ip_common ic;
if ((ip_get_common(&ic, &buf[p], size - p)) ||
(ic.size > size - p))
break;
tun_write(tun_fd, &buf[p], ic.size);
p += ic.size;
mud_send(mud, buf, (size_t)r, (h << 8) | ic.tc);
}
}
}
@@ -390,6 +338,7 @@ gt_bind(int argc, char **argv)
perror("tun_set_persist");
}
mud_delete(mud);
ctl_delete(ctl_fd);
return 0;

View File

@@ -64,7 +64,7 @@ gt_fromhex(uint8_t *dst, size_t dst_size, const char *src, size_t src_size)
if (_0_(a == -1 || b == -1))
return -1;
*dst++ = (a << 4) | b;
*dst++ = (uint8_t)((a << 4) | b);
}
return 0;
@@ -99,14 +99,18 @@ gt_get_port(struct sockaddr *sa)
int
gt_toaddr(char *str, size_t size, struct sockaddr *sa)
{
if (str)
str[0] = 0;
switch (sa->sa_family) {
case AF_INET:
return -!inet_ntop(AF_INET,
&((struct sockaddr_in *)sa)->sin_addr, str, size);
&((struct sockaddr_in *)sa)->sin_addr, str, (socklen_t)size);
case AF_INET6:
return -!inet_ntop(AF_INET6,
&((struct sockaddr_in6 *)sa)->sin6_addr, str, size);
&((struct sockaddr_in6 *)sa)->sin6_addr, str, (socklen_t)size);
}
errno = EAFNOSUPPORT;
return -1;
}

View File

@@ -21,6 +21,10 @@
#define PACKAGE_VERSION "0.0.0"
#endif
#ifndef GT_RUNDIR
#define GT_RUNDIR "/run/" PACKAGE_NAME
#endif
#define COUNT(x) (sizeof(x)/sizeof(x[0]))
#define ALIGN_SIZE (1<<4)

View File

@@ -2,15 +2,13 @@
#include "ctl.h"
#include "str.h"
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/un.h>
#define CTL_BIND_MAX 64
int
ctl_reply(int fd, struct ctl_msg *res, struct ctl_msg *req)
{
@@ -61,20 +59,20 @@ ctl_setsun(struct sockaddr_un *dst, const char *dir, const char *file)
static int
ctl_bind(int fd, const char *dir, const char *file)
{
char tmp[32];
struct sockaddr_un sun;
if (str_empty(file)) {
for (int i = 0; i < CTL_BIND_MAX; i++) {
if (snprintf(tmp, sizeof(tmp), ".%i", i) >= sizeof(tmp))
return -1;
char name[10] = { [0] = '.' };
unsigned pid = (unsigned)getpid();
if (ctl_setsun(&sun, dir, tmp))
return -1;
for (size_t i = 1; i < sizeof(name) - 1; i++, pid >>= 4)
name[i] = "uncopyrightables"[pid & 15];
if (!bind(fd, (struct sockaddr *)&sun, sizeof(sun)))
return 0;
}
if (ctl_setsun(&sun, dir, name))
return -1;
if (!bind(fd, (struct sockaddr *)&sun, sizeof(sun)))
return 0;
} else {
if (ctl_setsun(&sun, dir, file))
return -1;
@@ -94,7 +92,7 @@ ctl_delete(int fd)
if (fd == -1)
return;
struct sockaddr_storage ss;
struct sockaddr_storage ss = { 0 };
socklen_t sslen = sizeof(ss);
if ((getsockname(fd, (struct sockaddr *)&ss, &sslen) == 0) &&
@@ -133,13 +131,15 @@ ctl_create(const char *dir, const char *file)
int
ctl_connect(const char *dir, const char *file)
{
DIR *dp = NULL;
if (str_empty(dir)) {
errno = EINVAL;
return -1;
}
if (!file) {
DIR *dp = opendir(dir);
dp = opendir(dir);
if (!dp)
return -1;
@@ -152,19 +152,28 @@ ctl_connect(const char *dir, const char *file)
if (file) {
closedir(dp);
errno = ENOENT;
return -1;
return -3;
}
file = &d->d_name[0];
}
closedir(dp);
if (!file) {
closedir(dp);
return -2;
}
}
struct sockaddr_un sun;
const int ret = ctl_setsun(&sun, dir, file);
if (ctl_setsun(&sun, dir, file))
if (dp) {
int err = errno;
closedir(dp);
errno = err;
}
if (ret)
return -1;
int fd = ctl_create(dir, NULL);

View File

@@ -10,7 +10,7 @@ enum ctl_type {
CTL_STATUS,
CTL_MTU,
CTL_TC,
CTL_TIMEOUT,
CTL_KXTIMEOUT,
CTL_TIMETOLERANCE,
CTL_PATH_STATUS,
};
@@ -22,18 +22,20 @@ struct ctl_msg {
struct {
struct sockaddr_storage addr;
enum mud_state state;
unsigned long rate_tx;
unsigned long rate_rx;
} path;
struct mud_path path_status;
struct {
long pid;
size_t mtu;
int chacha;
struct sockaddr_storage bind;
struct sockaddr_storage peer;
} status;
int mtu;
size_t mtu;
int tc;
unsigned long timeout;
unsigned long timetolerance;
unsigned long ms;
};
};

View File

@@ -6,10 +6,15 @@
#include <sys/ioctl.h>
int
iface_set_mtu(const char *dev_name, int mtu)
iface_set_mtu(const char *dev_name, size_t mtu)
{
if (mtu > (size_t)0xFFFF) {
errno = EINVAL;
return -1;
}
struct ifreq ifr = {
.ifr_mtu = mtu,
.ifr_mtu = (int)mtu,
};
const size_t len = sizeof(ifr.ifr_name) - 1;

View File

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

112
src/ip.h
View File

@@ -3,15 +3,29 @@
#include <stdint.h>
struct ip_common {
uint8_t version;
uint8_t tc;
uint8_t proto;
uint8_t hdr_size;
uint16_t size;
struct { // data are not reordered
union {
unsigned char v6[16];
struct {
unsigned char zero[10];
unsigned char ff[2];
unsigned char v4[4];
};
};
unsigned char port[2];
} src, dst;
};
_pure_ static inline uint8_t
ip_get_version(const uint8_t *data, size_t size)
static inline int
ip_read16(const uint8_t *src)
{
return ((int)src[1]) | (((int)src[0]) << 8);
}
static inline uint8_t
ip_get_version(const uint8_t *data, int size)
{
if (size < 20)
return 0;
@@ -19,63 +33,65 @@ ip_get_version(const uint8_t *data, size_t size)
return data[0] >> 4;
}
static inline uint32_t
ip_read32(const uint8_t *src)
static inline int
ip_is_valid(const uint8_t *data, int size)
{
uint32_t ret = src[3];
ret |= ((uint32_t)src[2]) << 8;
ret |= ((uint32_t)src[1]) << 16;
ret |= ((uint32_t)src[0]) << 24;
return ret;
}
static inline uint16_t
ip_read16(const uint8_t *src)
{
uint16_t ret = src[1];
ret |= ((uint16_t)src[0]) << 8;
return ret;
}
static inline size_t
ip_get_mtu(struct ip_common *ic, const uint8_t *data, size_t size)
{
if (ic->hdr_size <= 0 || ic->hdr_size + 8 > size)
return 0;
const uint8_t *p = &data[ic->hdr_size];
if (ic->version == 4 && ic->proto == 1 && p[0] == 3)
return ip_read16(&p[6]);
// not tested..
// if (ic->version == 6 && ic->proto == 58 && p[0] == 2)
// return ip_read32(&p[4]);
switch (ip_get_version(data, size)) {
case 4: return size == ip_read16(&data[2]);
case 6: return size == ip_read16(&data[4]) + 40;
}
return 0;
}
static inline int
ip_get_common(struct ip_common *ic, const uint8_t *data, size_t size)
ip_get_common(struct ip_common *ic, const uint8_t *data, int size)
{
ic->version = ip_get_version(data, size);
switch (ic->version) {
switch (ip_get_version(data, size)) {
case 4:
ic->tc = data[1];
ic->proto = data[9];
ic->hdr_size = (data[0] & 0xF) << 2;
ic->size = ip_read16(&data[2]);
if (ic->size >= 20)
if (size == ip_read16(&data[2])) {
const int hdrsize = (data[0] & 0xF) << 2;
memset(ic->src.zero, 0, sizeof(ic->src.zero));
memset(ic->src.ff, 0xff, sizeof(ic->src.ff));
memcpy(ic->src.v4, &data[12], sizeof(ic->src.v4));
memset(ic->dst.zero, 0, sizeof(ic->dst.zero));
memset(ic->dst.ff, 0xff, sizeof(ic->dst.ff));
memcpy(ic->dst.v4, &data[16], sizeof(ic->dst.v4));
switch (ic->proto) {
case 6: // tcp
case 17: // udp
memcpy(ic->src.port, &data[hdrsize], sizeof(ic->src.port));
memcpy(ic->dst.port, &data[hdrsize + 2], sizeof(ic->dst.port));
break;
default:
memset(ic->src.port, 0, sizeof(ic->src.port));
memset(ic->dst.port, 0, sizeof(ic->dst.port));
}
return 0;
}
break;
case 6:
ic->tc = ((data[0] & 0xF) << 4) | (data[1] >> 4);
ic->tc = (uint8_t)((data[0] << 4) | (data[1] >> 4));
ic->proto = data[6];
ic->hdr_size = 40;
ic->size = ip_read16(&data[4]) + 40;
return 0;
if (size == ip_read16(&data[4]) + 40) {
memcpy(ic->src.v6, &data[8], sizeof(ic->src.v6));
memcpy(ic->dst.v6, &data[24], sizeof(ic->dst.v6));
switch (ic->proto) {
case 6: // tcp
case 17: // udp
memcpy(ic->src.port, &data[40], sizeof(ic->src.port));
memcpy(ic->dst.port, &data[42], sizeof(ic->dst.port));
break;
default:
memset(ic->src.port, 0, sizeof(ic->src.port));
memset(ic->dst.port, 0, sizeof(ic->dst.port));
}
return 0;
}
break;
}
return -1;
return 1;
}

View File

@@ -8,7 +8,7 @@ volatile sig_atomic_t gt_reload;
volatile sig_atomic_t gt_quit;
static void
gt_quit_handler(int sig)
gt_sa_handler(int sig)
{
switch (sig) {
case SIGALRM:
@@ -30,7 +30,7 @@ gt_set_signal(void)
sigemptyset(&sa.sa_mask);
sa.sa_handler = gt_quit_handler;
sa.sa_handler = gt_sa_handler;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
@@ -69,15 +69,14 @@ main(int argc, char **argv)
{"version", "show version", gt_version},
{NULL}};
if (argc < 2)
return gt_show(argc, argv);
for (int k = 0; cmd[k].name; k++) {
if (!str_cmp(cmd[k].name, argv[1]))
return cmd[k].call(argc - 1, argv + 1);
if (argv[1]) {
for (int k = 0; cmd[k].name; k++) {
if (!str_cmp(cmd[k].name, argv[1]))
return cmd[k].call(argc - 1, argv + 1);
}
}
printf("unknown command `%s', available commands:\n\n", argv[1]);
printf("available commands:\n\n");
int len = 0;

View File

@@ -4,10 +4,11 @@
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include "../argz/argz.h"
int
static int
gt_path_status(int fd)
{
struct ctl_msg req = {
@@ -17,19 +18,29 @@ gt_path_status(int fd)
if (send(fd, &req, sizeof(struct ctl_msg), 0) == -1)
return -1;
int term = isatty(1);
do {
if (recv(fd, &res, sizeof(struct ctl_msg), 0) == -1)
return -1;
char bindstr[INET6_ADDRSTRLEN] = {0};
char peerstr[INET6_ADDRSTRLEN] = {0};
if (gt_toaddr(bindstr, sizeof(bindstr),
(struct sockaddr *)&res.path_status.local_addr) ||
gt_toaddr(peerstr, sizeof(peerstr),
(struct sockaddr *)&res.path_status.addr))
if (res.type != req.type)
return -2;
if (!res.ret)
return 0;
char bindstr[INET6_ADDRSTRLEN];
char publstr[INET6_ADDRSTRLEN];
char peerstr[INET6_ADDRSTRLEN];
gt_toaddr(bindstr, sizeof(bindstr),
(struct sockaddr *)&res.path_status.local_addr);
gt_toaddr(publstr, sizeof(publstr),
(struct sockaddr *)&res.path_status.r_addr);
gt_toaddr(peerstr, sizeof(peerstr),
(struct sockaddr *)&res.path_status.addr);
const char *statestr = NULL;
switch (res.path_status.state) {
@@ -39,14 +50,46 @@ gt_path_status(int fd)
default: return -2;
}
printf("path %s\n"
" bind: %s\n"
" peer: %s port %"PRIu16"\n"
" rtt: %.3f\n",
statestr, bindstr, peerstr,
gt_get_port((struct sockaddr *)&res.path_status.addr),
res.path_status.rtt/(double)1e3);
const char *statusstr = res.path_status.ok ? "OK" : "DEGRADED";
printf(term ? "path %s\n"
" status: %s\n"
" bind: %s port %"PRIu16"\n"
" public: %s port %"PRIu16"\n"
" peer: %s port %"PRIu16"\n"
" mtu: %zu bytes\n"
" rtt: %.3f ms\n"
" rttvar: %.3f ms\n"
" rate tx: %"PRIu64" bytes/sec\n"
" rate rx: %"PRIu64" bytes/sec\n"
" total tx: %"PRIu64" packets\n"
" total rx: %"PRIu64" packets\n"
: "path %s %s"
" %s %"PRIu16
" %s %"PRIu16
" %s %"PRIu16
" %zu"
" %.3f %.3f"
" %"PRIu64
" %"PRIu64
" %"PRIu64
" %"PRIu64
"\n",
statestr,
statusstr,
bindstr[0] ? bindstr : "-",
gt_get_port((struct sockaddr *)&res.path_status.local_addr),
publstr[0] ? publstr : "-",
gt_get_port((struct sockaddr *)&res.path_status.r_addr),
peerstr[0] ? peerstr : "-",
gt_get_port((struct sockaddr *)&res.path_status.addr),
res.path_status.mtu.ok,
(double)res.path_status.rtt.val / 1e3,
(double)res.path_status.rtt.var / 1e3,
res.path_status.rate_tx,
res.path_status.rate_rx,
res.path_status.send.total,
res.path_status.recv.total);
} while (res.ret == EAGAIN);
return 0;
@@ -61,20 +104,37 @@ gt_path(int argc, char **argv)
.type = CTL_STATE,
}, res = {0};
struct argz ratez[] = {
{"tx", "BYTES/SEC", &req.path.rate_tx, argz_bytes},
{"rx", "BYTES/SEC", &req.path.rate_rx, argz_bytes},
{NULL}};
struct argz pathz[] = {
{NULL, "IPADDR", &req.path.addr, argz_addr},
{"dev", "NAME", &dev, argz_str},
{"up|backup|down", NULL, NULL, argz_option},
{"rate", NULL, &ratez, argz_option},
{NULL}};
if (argz(pathz, argc, argv))
return 1;
int fd = ctl_connect("/run/" PACKAGE_NAME, dev);
int fd = ctl_connect(GT_RUNDIR, dev);
if (fd == -1) {
perror("path");
ctl_delete(fd);
if (fd < 0) {
switch (fd) {
case -1:
perror("path");
break;
case -2:
gt_log("no device\n");
break;
case -3:
gt_log("please choose a device\n");
break;
default:
gt_log("couldn't connect\n");
}
return 1;
}
@@ -86,6 +146,8 @@ gt_path(int argc, char **argv)
if (ret == -2)
gt_log("bad reply from server\n");
} else {
req.path.state = MUD_EMPTY;
if (argz_is_set(pathz, "up")) {
req.path.state = MUD_UP;
} else if (argz_is_set(pathz, "backup")) {
@@ -94,8 +156,7 @@ gt_path(int argc, char **argv)
req.path.state = MUD_DOWN;
}
if (req.path.state)
ret = ctl_reply(fd, &res, &req);
ret = ctl_reply(fd, &res, &req);
}
if (ret == -1)
@@ -103,5 +164,5 @@ gt_path(int argc, char **argv)
ctl_delete(fd);
return 0;
return !!ret;
}

View File

@@ -22,23 +22,23 @@ gt_set_mtu(int fd, size_t mtu)
return 1;
}
printf("mtu set to %i\n", res.mtu);
printf("mtu set to %zu\n", res.mtu);
return 0;
}
static int
gt_set_timeout(int fd, unsigned long timeout)
gt_set_kxtimeout(int fd, unsigned long ms)
{
struct ctl_msg res, req = {
.type = CTL_TIMEOUT,
.timeout = timeout,
.type = CTL_KXTIMEOUT,
.ms = ms,
};
int ret = ctl_reply(fd, &res, &req);
if (ret) {
perror("set timeout");
perror("set kxtimeout");
return 1;
}
@@ -46,11 +46,11 @@ gt_set_timeout(int fd, unsigned long timeout)
}
static int
gt_set_timetolerance(int fd, unsigned long timetolerance)
gt_set_timetolerance(int fd, unsigned long ms)
{
struct ctl_msg res, req = {
.type = CTL_TIMETOLERANCE,
.timetolerance = timetolerance,
.ms = ms,
};
int ret = ctl_reply(fd, &res, &req);
@@ -113,24 +113,36 @@ gt_set(int argc, char **argv)
const char *dev = NULL;
size_t mtu;
int tc;
unsigned long kxtimeout;
unsigned long timetolerance;
unsigned long timeout;
struct argz pathz[] = {
{"dev", "NAME", &dev, argz_str},
{"mtu", "BYTES", &mtu, argz_bytes},
{"tc", "CS|AF|EF", &tc, gt_argz_tc},
{"timeout", "SECONDS", &timeout, argz_time},
{"kxtimeout", "SECONDS", &kxtimeout, argz_time},
{"timetolerance", "SECONDS", &timetolerance, argz_time},
{NULL}};
if (argz(pathz, argc, argv))
return 1;
int fd = ctl_connect("/run/" PACKAGE_NAME, dev);
int fd = ctl_connect(GT_RUNDIR, dev);
if (fd == -1) {
perror("set");
if (fd < 0) {
switch (fd) {
case -1:
perror("set");
break;
case -2:
gt_log("no device\n");
break;
case -3:
gt_log("please choose a device\n");
break;
default:
gt_log("couldn't connect\n");
}
return 1;
}
@@ -142,8 +154,8 @@ gt_set(int argc, char **argv)
if (argz_is_set(pathz, "tc"))
ret |= gt_set_tc(fd, tc);
if (argz_is_set(pathz, "timeout"))
ret |= gt_set_timeout(fd, timeout);
if (argz_is_set(pathz, "kxtimeout"))
ret |= gt_set_kxtimeout(fd, kxtimeout);
if (argz_is_set(pathz, "timetolerance"))
ret |= gt_set_timetolerance(fd, timetolerance);

View File

@@ -9,6 +9,7 @@
#include <dirent.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <unistd.h>
static int
gt_show_dev_status(int fd, const char *dev)
@@ -18,34 +19,55 @@ gt_show_dev_status(int fd, const char *dev)
if (ctl_reply(fd, &res, &req))
return -1;
char bindstr[INET6_ADDRSTRLEN] = {0};
char peerstr[INET6_ADDRSTRLEN] = {0};
char bindstr[INET6_ADDRSTRLEN];
char peerstr[INET6_ADDRSTRLEN];
if (gt_toaddr(bindstr, sizeof(bindstr),
(struct sockaddr *)&res.status.bind))
return -2;
gt_toaddr(bindstr, sizeof(bindstr),
(struct sockaddr *)&res.status.bind);
int server = gt_toaddr(peerstr, sizeof(peerstr),
(struct sockaddr *)&res.status.peer);
int term = isatty(1);
if (server) {
printf("server %s:\n"
" bind: %s port %"PRIu16"\n"
" mtu: %zu\n"
" cipher: %s\n",
printf(term ? "server %s:\n"
" pid: %li\n"
" bind: %s port %"PRIu16"\n"
" mtu: %zu\n"
" cipher: %s\n"
: "server %s"
" %li"
" %s %"PRIu16
" %zu"
" %s"
"\n",
dev,
bindstr, gt_get_port((struct sockaddr *)&res.status.bind),
res.status.pid,
bindstr[0] ? bindstr : "-",
gt_get_port((struct sockaddr *)&res.status.bind),
res.status.mtu,
res.status.chacha ? "chacha20poly1305" : "aes256gcm");
} else {
printf("client %s:\n"
" bind: %s port %"PRIu16"\n"
" peer: %s port %"PRIu16"\n"
" mtu: %zu\n"
" cipher: %s\n",
printf(term ? "client %s:\n"
" pid: %li\n"
" bind: %s port %"PRIu16"\n"
" peer: %s port %"PRIu16"\n"
" mtu: %zu\n"
" cipher: %s\n"
: "client %s"
" %li"
" %s %"PRIu16
" %s %"PRIu16
" %zu"
" %s"
"\n",
dev,
bindstr, gt_get_port((struct sockaddr *)&res.status.bind),
peerstr, gt_get_port((struct sockaddr *)&res.status.peer),
res.status.pid,
bindstr[0] ? bindstr : "-",
gt_get_port((struct sockaddr *)&res.status.bind),
peerstr[0] ? peerstr : "-",
gt_get_port((struct sockaddr *)&res.status.peer),
res.status.mtu,
res.status.chacha ? "chacha20poly1305" : "aes256gcm");
}
@@ -56,10 +78,11 @@ gt_show_dev_status(int fd, const char *dev)
static int
gt_show_dev(const char *dev)
{
int fd = ctl_connect("/run/" PACKAGE_NAME, dev);
int fd = ctl_connect(GT_RUNDIR, dev);
if (fd == -1) {
perror(dev);
if (fd < 0) {
if (fd == -1)
perror("show");
return -1;
}
@@ -88,12 +111,10 @@ gt_show(int argc, char **argv)
if (argz(showz, argc, argv))
return 1;
if (dev) {
gt_show_dev(dev);
return 0;
}
if (dev)
return !!gt_show_dev(dev);
DIR *dp = opendir("/run/" PACKAGE_NAME);
DIR *dp = opendir(GT_RUNDIR);
if (!dp) {
if (errno == ENOENT)
@@ -102,14 +123,15 @@ gt_show(int argc, char **argv)
return 1;
}
int ret = 0;
struct dirent *d = NULL;
while (d = readdir(dp), d) {
if (d->d_name[0] != '.')
gt_show_dev(d->d_name);
ret |= !!gt_show_dev(d->d_name);
}
closedir(dp);
return 0;
return ret;
}

View File

@@ -129,10 +129,9 @@ static int
tun_create_by_name(char *name, size_t len, const char *dev_name)
{
char tmp[128];
int ret = snprintf(tmp, sizeof(tmp), "/dev/%s", dev_name);
if (ret <= 0 || ret >= sizeof(tmp)) {
if (ret <= 0 || (size_t)ret >= sizeof(tmp)) {
errno = EINVAL;
return -1;
}
@@ -153,10 +152,9 @@ static int
tun_create_by_id(char *name, size_t len, unsigned id)
{
char tmp[64];
int ret = snprintf(tmp, sizeof(tmp), "tun%u", id);
if (ret <= 0 || ret >= sizeof(tmp)) {
if (ret <= 0 || (size_t)ret >= sizeof(tmp)) {
errno = EINVAL;
return -1;
}
@@ -201,17 +199,17 @@ tun_read(int fd, void *data, size_t size)
},
};
ssize_t ret = readv(fd, iov, 2);
int ret = (int)readv(fd, iov, 2);
if (ret <= (ssize_t)0)
if (ret <= 0)
return ret;
if (ret <= (ssize_t)sizeof(family))
if ((size_t)ret <= sizeof(family))
return 0;
return ret - sizeof(family);
return ret - (int)sizeof(family);
#else
return read(fd, data, size);
return (int)read(fd, data, size);
#endif
}
@@ -224,7 +222,7 @@ tun_write(int fd, const void *data, size_t size)
#ifdef GT_BSD_TUN
uint32_t family;
switch (ip_get_version(data, size)) {
switch (ip_get_version(data, (int)size)) {
case 4:
family = htonl(AF_INET);
break;
@@ -247,17 +245,17 @@ tun_write(int fd, const void *data, size_t size)
},
};
ssize_t ret = writev(fd, iov, 2);
int ret = (int)writev(fd, iov, 2);
if (ret <= (ssize_t)0)
if (ret <= 0)
return ret;
if (ret <= (ssize_t)sizeof(family))
if ((size_t)ret <= sizeof(family))
return 0;
return ret - sizeof(family);
return ret - (int)sizeof(family);
#else
return write(fd, data, size);
return (int)write(fd, data, size);
#endif
}

View File

@@ -59,7 +59,9 @@ TABLE=200
# keep the current route to HOST
SRC=$(ip route get "$HOST" | awk '/src/{getline;print $0}' RS=' ')
ip rule add from "$SRC" table main pref "$((PREF-1))" || true
glorytun path up "$SRC" dev "$DEV"
# limit to 100Mbit by default
glorytun path up "$SRC" dev "$DEV" rate rx 12500000 tx 12500000
# forward everything else to the tunnel
ip rule add from all table "$TABLE" pref "$PREF" || true

View File

@@ -1,13 +1,15 @@
#!/bin/sh
[ -z "${VERSION}" ] && VERSION=`git describe --tags --match='v[0-9].*' 2>/dev/null` \
&& VERSION=${VERSION#v}
export GIT_DIR=.git
export GIT_WORK_TREE=.
[ -z "${VERSION}" ] && VERSION=`cat VERSION 2>/dev/null`
[ -z "$VERSION" ] && VERSION="$(git describe --tags --match='v[0-9].*' 2>/dev/null)" \
&& VERSION="${VERSION#v}"
[ -z "${VERSION}" ] && VERSION=0.0.0
[ -z "$VERSION" ] && VERSION="$(git rev-parse HEAD 2>/dev/null)"
[ "$1" = "major" ] && printf ${VERSION%%.*} \
&& exit 0
[ -z "$VERSION" ] && VERSION="$(cat VERSION 2>/dev/null)"
printf ${VERSION} | tee VERSION
[ -z "$VERSION" ] && VERSION="0.0.0"
printf "%s" "$VERSION" | tee VERSION