Skip to content
This repository has been archived by the owner on Dec 27, 2019. It is now read-only.

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
zx2c4 committed Jun 25, 2016
0 parents commit 99d303a
Show file tree
Hide file tree
Showing 88 changed files with 14,854 additions and 0 deletions.
10 changes: 10 additions & 0 deletions .gitignore
@@ -0,0 +1,10 @@
cscope.out
*.o
*.ko
*.mod.c
Module.symvers
*.cmd
.tmp_versions
*.swp
modules.order
modules.builtin
339 changes: 339 additions & 0 deletions COPYING

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions README.md
@@ -0,0 +1,10 @@
# WireGuard — fast, modern, secure kernel VPN tunnel
#### by [Jason A. Donenfeld](mailto:Jason@zx2c4.com) of [Edge Security](http://www.edgesecurity.com/)

WireGuard is a novel VPN that runs inside the Linux Kernel and utilizes **state-of-the-art [cryptography](doc/protocol.md)**. It aims to be faster, simpler, leaner, and more useful than IPSec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN. WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many different circumstances. It runs over UDP.

**More information may be found at [WireGuard.io](https://www.wireguard.io/).**

## License

This project is released under the [GPLv2](COPYING).
8 changes: 8 additions & 0 deletions contrib/benchmarking/configs/other.conf
@@ -0,0 +1,8 @@
[Interface]
ListenPort = 27183
PrivateKey = oHilodMrwJSD1UUIkAkyCek2yqy1Frs5XuN47ShGFk0=

[Peer]
PublicKey = S8hEvD+dam+PrwG4GrSPtE2Pl3ylO/oiUnUDXw3vnx0=
AllowedIPs = 192.168.2.2/32
Endpoint = 10.10.10.100:38292
8 changes: 8 additions & 0 deletions contrib/benchmarking/configs/thinkpad.conf
@@ -0,0 +1,8 @@
[Interface]
ListenPort = 38292
PrivateKey = MPCo/WSBkm/DCkbEXUhtjc5u//IeD6wEeaw3Q2HxFGw=

[Peer]
PublicKey = c5PwaIZcVZFDuoDdQJGnYe+fk+wt0qANARpnZDOvqhw=
AllowedIPs = 0.0.0.0/0
Endpoint = 172.16.48.128:27183
2 changes: 2 additions & 0 deletions contrib/benchmarking/openvpn-config.txt
@@ -0,0 +1,2 @@
Server: openvpn --dev tun --ifconfig 192.168.3.1 192.168.3.2 --secret static.key --cipher AES-256-CBC --auth SHA256 --port 61721
Client: openvpn --dev tun --ifconfig 192.168.3.2 192.168.3.1 --secret static.key --cipher AES-256-CBC --auth SHA256 --port 61721 --remote 10.10.10.1
21 changes: 21 additions & 0 deletions contrib/benchmarking/static.key
@@ -0,0 +1,21 @@
#
# 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----
12abb34ac1cb716576642c7e4c9719af
b311929f6bb5a7b9082c9ac3a02dc77a
26fc65ba97e67d1dc5b273e72760caba
6c8a3321acdf89bfd0469528bfc9ed89
1c9c3762d1e18786c8b6dd590456f158
d1f625810da1225864c23d7e848ca5d7
18a49c4b7e640f8e51001ace9222de75
e05177fd01b32d702bd12b45b085678c
239e3927d98912174ac648d0e37a3247
45cabcbea7cf70832f8800a8b863a35a
933c5921fd65882b050bd1096a0c6c60
638fb22eafb9f49c13573236d0427441
c98869ba8de30e597452237527e7dcc6
519058a919de4432203dc1d7622fb4d0
f8f20c5350256cdf17bb3b85c5c838fc
6ddeb4da9dae8b0b882cb043db483a9d
-----END OpenVPN Static key V1-----
20 changes: 20 additions & 0 deletions contrib/client-server-example/client.sh
@@ -0,0 +1,20 @@
#!/bin/bash
set -e
[[ $UID == 0 ]] || { echo "You must be root to run this."; exit 1; }
umask 077
trap 'rm -f /tmp/wg_private_key' EXIT INT TERM
exec 3<>/dev/tcp/demo.wireguard.io/42912
wg genkey | tee /tmp/wg_private_key | wg pubkey >&3
IFS=: read -r status server_pubkey server_port internal_ip <&3
[[ $status == OK ]]
ip link del dev wg0 2>/dev/null || true
ip link add dev wg0 type wireguard
wg set wg0 private-key /tmp/wg_private_key peer "$server_pubkey" allowed-ips 0.0.0.0/0 endpoint "demo.wireguard.io:$server_port"
ip address add "$internal_ip"/24 dev wg0
ip link set up dev wg0
if [ "$1" == "default-route" ]; then
host="$(wg show wg0 endpoints | sed -n 's/.*\t\(.*\):.*/\1/p')"
ip route add $(ip route get $host | sed '/ via [0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/{s/^\(.* via [0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/}' | head -n 1) 2>/dev/null || true
ip route add 0/1 dev wg0
ip route add 128/1 dev wg0
fi
14 changes: 14 additions & 0 deletions contrib/client-server-example/server.sh
@@ -0,0 +1,14 @@
#!/bin/bash
if [[ -z $NCAT_REMOTE_ADDR ]]; then
ip link del dev wg0 2>/dev/null
set -e
ip link add dev wg0 type wireguard
ip address add 192.168.4.1/24 dev wg0
wg set wg0 private-key <(wg genkey) listen-port 12912
ip link set up dev wg0
exec ncat -e "$(readlink -f "$0")" -k -l -p 42912 -v
fi
read -r public_key
[[ $(wg show wg0 | grep peer | wc -l) -ge 253 ]] && wg set wg0 peer $(wg show wg0 latest-handshakes | sort -k 2 -b -n | head -n 1 | cut -f 1) remove
next_ip=$(all="$(wg show wg0 allowed-ips)"; for ((i=2; i<=254; i++)); do ip="192.168.4.$i"; [[ $all != *$ip/32* ]] && echo $ip && break; done)
wg set wg0 peer "$public_key" allowed-ips $next_ip/32 2>/dev/null && echo "OK:$(wg show wg0 private-key | wg pubkey):$(wg show wg0 listen-port):$next_ip" || echo ERROR
63 changes: 63 additions & 0 deletions contrib/external-tests/go/main.go
@@ -0,0 +1,63 @@
/* Copyright 2015-2016 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */

package main

import (
"github.com/titanous/noise"
"net"
"time"
"bytes"
"crypto/rand"
"encoding/base64"
"encoding/binary"
"github.com/dchest/blake2s"
)

func assert(exp bool) {
if !exp {
panic("Assertion failed.")
}
}

func main() {
my_private, _ := base64.StdEncoding.DecodeString("WAmgVYXkbT2bCtdcDwolI88/iVi/aV3/PHcUBTQSYmo=")
my_public, _ := base64.StdEncoding.DecodeString("K5sF9yESrSBsOXPd6TcpKNgqoy1Ik3ZFKl4FolzrRyI=")
preshared, _ := base64.StdEncoding.DecodeString("FpCyhws9cxwWoV4xELtfJvjJN+zQVRPISllRWgeopVE=")
their_public, _ := base64.StdEncoding.DecodeString("qRCwZSKInrMAq5sepfCdaCsRJaoLe5jhtzfiw7CjbwM=")
cs := noise.NewCipherSuite(noise.DH25519, noise.CipherChaChaPoly, noise.HashBLAKE2s)
hs := noise.NewHandshakeState(noise.Config{CipherSuite: cs, Random: rand.Reader, Pattern: noise.HandshakeIK, Initiator: true, Prologue: []byte("WireGuard v0 zx2c4 Jason@zx2c4.com"), PresharedKey: preshared, StaticKeypair: noise.DHKey{Private: my_private, Public: my_public}, PeerStatic: their_public})
conn, _ := net.Dial("udp", "test.wireguard.io:51820")

now := time.Now()
tai64n := make([]byte, 12)
binary.BigEndian.PutUint64(tai64n[:], uint64(now.Unix()))
binary.BigEndian.PutUint32(tai64n[8:], uint32(now.UnixNano()))
initiation_packet := make([]byte, 5)
initiation_packet[0] = 1 /* Type: Initiation */
binary.LittleEndian.PutUint32(initiation_packet[1:], 28) /* Sender index: 28 (arbitrary) */
initiation_packet, _, _ = hs.WriteMessage(initiation_packet, tai64n)
hasher, _ := blake2s.New(&blake2s.Config{Size: 16, Key: preshared})
hasher.Write(their_public)
hasher.Write(initiation_packet)
initiation_packet = append(initiation_packet, hasher.Sum(nil)[:16]...)
initiation_packet = append(initiation_packet, bytes.Repeat([]byte{ 0 }, 16)...)
conn.Write(initiation_packet)

response_packet := make([]byte, 89)
conn.Read(response_packet)
assert(response_packet[0] == 2 /* Type: Response */)
their_index := binary.LittleEndian.Uint32(response_packet[1:])
our_index := binary.LittleEndian.Uint32(response_packet[5:])
assert(our_index == 28)
payload, send_cs, _, err := hs.ReadMessage(nil, response_packet[9:57])
assert(len(payload) == 0 && err == nil)

keepalive_packet := make([]byte, 13)
keepalive_packet[0] = 4 /* Type: Data */
binary.LittleEndian.PutUint32(keepalive_packet[1:], their_index)
binary.LittleEndian.PutUint64(keepalive_packet[3:], 0) /* Nonce */
keepalive_packet = send_cs.Encrypt(keepalive_packet, nil, nil)
conn.Write(keepalive_packet)

conn.Close()
}
2 changes: 2 additions & 0 deletions contrib/external-tests/haskell/Setup.hs
@@ -0,0 +1,2 @@
import Distribution.Simple
main = defaultMain
34 changes: 34 additions & 0 deletions contrib/external-tests/haskell/cacophony-wg.cabal
@@ -0,0 +1,34 @@
-- Initial cacophony-wg.cabal generated by cabal init. For further
-- documentation, see http://haskell.org/cabal/users-guide/

name: cacophony-wg
version: 0.1.0
-- synopsis:
-- description:
license: PublicDomain
license-file: LICENSE
author: John Galt
maintainer: centromere@users.noreply.github.com
-- copyright:
-- category:
build-type: Simple
-- extra-source-files:
cabal-version: >=1.10

executable cacophony-wg
main-is: Main.hs
other-modules:
Data.Time.TAI64
build-depends:
base >=4.8 && <4.9,
base16-bytestring,
base64-bytestring,
blake2,
bytestring,
cacophony,
cereal,
cryptonite,
network,
time
hs-source-dirs: src
default-language: Haskell2010
86 changes: 86 additions & 0 deletions contrib/external-tests/haskell/src/Data/Time/TAI64.hs
@@ -0,0 +1,86 @@
module Data.Time.TAI64 (
TAI64(..)
, TAI64N(..)
, TAI64NA(..)
, posixToTAI64
, posixToTAI64N
, posixToTAI64NA
, getCurrentTAI64
, getCurrentTAI64N
, getCurrentTAI64NA
, tAI64ToPosix
, tAI64NToPosix
, tAI64NAToPosix
) where

import Data.Serialize
import Control.Monad
import Data.Word

import Data.Time.Clock
import Data.Time.Clock.POSIX

import Numeric

data TAI64 = TAI64
{-# UNPACK #-} !Word64
deriving (Eq, Ord)

data TAI64N = TAI64N
{-# UNPACK #-} !TAI64
{-# UNPACK #-} !Word32
deriving (Eq, Ord, Show)

data TAI64NA = TAI64NA
{-# UNPACK #-} !TAI64N
{-# UNPACK #-} !Word32
deriving (Eq, Ord, Show)

instance Show TAI64 where
show (TAI64 t) = "TAI64 0x" ++ showHex t ""

instance Serialize TAI64 where
put (TAI64 t) = putWord64be t
get = liftM TAI64 get

instance Serialize TAI64N where
put (TAI64N t' nt) = put t' >> putWord32be nt
get = liftM2 TAI64N get get

instance Serialize TAI64NA where
put (TAI64NA t' at) = put t' >> putWord32be at
get = liftM2 TAI64NA get get


posixToTAI64 :: POSIXTime -> TAI64
posixToTAI64 = TAI64 . (2^62 +) . truncate . realToFrac

posixToTAI64N :: POSIXTime -> TAI64N
posixToTAI64N pt = TAI64N t' ns where
t' = posixToTAI64 pt
ns = (`mod` 10^9) $ truncate (pts * 10**9)
pts = realToFrac pt

posixToTAI64NA :: POSIXTime -> TAI64NA -- | PICOsecond precision
posixToTAI64NA pt = TAI64NA t' as where
t' = posixToTAI64N pt
as = (`mod` 10^9) $ truncate (pts * 10**18)
pts = realToFrac pt

getCurrentTAI64 :: IO TAI64
getCurrentTAI64N :: IO TAI64N
getCurrentTAI64NA :: IO TAI64NA
getCurrentTAI64 = liftM posixToTAI64 getPOSIXTime
getCurrentTAI64N = liftM posixToTAI64N getPOSIXTime
getCurrentTAI64NA = liftM posixToTAI64NA getPOSIXTime

tAI64ToPosix :: TAI64 -> POSIXTime
tAI64ToPosix (TAI64 s) = fromRational . fromIntegral $ s - 2^62

tAI64NToPosix :: TAI64N -> POSIXTime
tAI64NToPosix (TAI64N t' n) = tAI64ToPosix t' + nanopart where
nanopart = fromRational $ (toRational $ 10**(-9)) * toRational n -- TODO: optimize?

tAI64NAToPosix :: TAI64NA -> POSIXTime
tAI64NAToPosix (TAI64NA t' a) = tAI64NToPosix t' + attopart where
attopart = fromRational $ (toRational $ 10**(-18)) * toRational a
81 changes: 81 additions & 0 deletions contrib/external-tests/haskell/src/Main.hs
@@ -0,0 +1,81 @@
{-# LANGUAGE OverloadedStrings #-}
module Main where

import Control.Applicative ((<$>))
import Control.Concurrent.MVar
import Control.Monad (void)
import Data.ByteString.Char8 (pack, unpack, take, drop, replicate)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Base16 as Hex
import qualified Data.ByteString.Base64 as B64
import qualified Data.Serialize as S
import Prelude hiding (take, drop, replicate)
import System.Environment
import Network.Socket
import qualified Network.Socket.ByteString as NBS

import Crypto.Hash.BLAKE2.BLAKE2s
import Crypto.Noise.Cipher
import Crypto.Noise.Cipher.ChaChaPoly1305
import Crypto.Noise.Curve
import Crypto.Noise.Curve.Curve25519
import Crypto.Noise.Handshake
import Crypto.Noise.HandshakePatterns
import Crypto.Noise.Hash.BLAKE2s
import Crypto.Noise.Types

import Data.Time.TAI64

w :: PublicKey Curve25519
-> Plaintext
-> Socket
-> SockAddr
-> ByteString
-> IO ()
w theirPub (Plaintext myPSK) sock addr msg = do
let x = "\x01\x00\x00" `mappend` msg
mac = hash 16 myPSK (sbToBS' (curvePubToBytes theirPub) `mappend` sbToBS' x)
void $ NBS.sendTo sock (x `mappend` mac `mappend` replicate 16 '\0') addr

r :: MVar ByteString -> Socket -> IO ByteString
r smv sock = do
(r, _) <- NBS.recvFrom sock 1024
putMVar smv $ (take 2 . drop 1) r
return . take 48 . drop 5 $ r

payload :: IO Plaintext
payload = do
tai64n <- getCurrentTAI64N
return . Plaintext . bsToSB' $ S.encode tai64n

main :: IO ()
main = do
let ip = "test.wireguard.io"
let port = "51820"
let mykey = "WAmgVYXkbT2bCtdcDwolI88/iVi/aV3/PHcUBTQSYmo="
let serverkey = "qRCwZSKInrMAq5sepfCdaCsRJaoLe5jhtzfiw7CjbwM="
let psk = "FpCyhws9cxwWoV4xELtfJvjJN+zQVRPISllRWgeopVE="
addrInfo <- head <$> getAddrInfo Nothing (Just ip) (Just port)
sock <- socket (addrFamily addrInfo) Datagram defaultProtocol

let addr = addrAddress addrInfo
mykey' = curveBytesToPair . bsToSB' . either undefined id . B64.decode . pack $ mykey :: KeyPair Curve25519
serverkey' = curveBytesToPub . bsToSB' . either undefined id . B64.decode . pack $ serverkey :: PublicKey Curve25519
psk' = Plaintext . bsToSB' . either undefined id . B64.decode . pack $ psk
hs = handshakeState $ HandshakeStateParams
noiseIK
"WireGuard v0 zx2c4 Jason@zx2c4.com"
(Just psk')
(Just mykey')
Nothing
(Just serverkey')
Nothing
True :: HandshakeState ChaChaPoly1305 Curve25519 BLAKE2s

senderindexmv <- newEmptyMVar
let hc = HandshakeCallbacks (w serverkey' psk' sock addr) (r senderindexmv sock) (\_ -> return ()) payload
(encryption, decryption) <- runHandshake hs hc

let (keepAlive, encryption') = encryptPayload "" encryption
senderindex <- takeMVar senderindexmv
void $ NBS.sendTo sock ("\x04" `mappend` senderindex `mappend` replicate 8 '\0' `mappend` keepAlive) addr
2 changes: 2 additions & 0 deletions contrib/external-tests/rust/.gitignore
@@ -0,0 +1,2 @@
Cargo.lock
target/
10 changes: 10 additions & 0 deletions contrib/external-tests/rust/Cargo.toml
@@ -0,0 +1,10 @@
[package]
name = "wireguard-keepalive"
version = "0.1.0"
authors = ["jason@zx2c4.com"]
[dependencies]
screech = { git = "https://github.com/trevp/screech" }
rust-crypto = "*"
byteorder = "*"
rustc-serialize = "*"
time = "*"

0 comments on commit 99d303a

Please sign in to comment.