--- /dev/null
+GOPATH != pwd
+VERSION != cat VERSION
+
+include common.mk
--- /dev/null
+GOPATH = $(shell pwd)
+VERSION = $(shell cat VERSION)
+
+include common.mk
-GOPATH != pwd
-VERSION != cat VERSION
-
LDFLAGS = -X govpn.Version $(VERSION)
PREFIX ?= /usr/local
BINDIR = $(DESTDIR)$(PREFIX)/bin
@tab @url{download/govpn-3.1.tar.xz, link} @url{download/govpn-3.1.tar.xz.sig, sign}
@tab @code{4034a67eb472e33760ed1783ca871f531c3a6be99b9bd6213f4f83c1147c344b}
+@item 3.2 @tab 174 KiB
+@tab @url{download/govpn-3.2.tar.xz, link} @url{download/govpn-3.2.tar.xz.sig, sign}
+@tab @code{388e98d6adef5ebf3431b0d48419f54d2e2064c657de67e23c669ebcf273126d}
+
@end multitable
Also you can try its @ref{Contacts, .onion} version.
is 1432.
@end itemize
+@strong{Install}. At first you must @ref{Installation, install} this
+software: download, check the signature, compile.
+
Do not forget about setting @code{GOMAXPROC} environment variable for
-using more than one CPU.
+using more than one CPU on both sides:
+
+@example
+% export GOMAXPROC=4
+@end example
+
+@strong{Prepare the server}. Create the new client, named (for example)
+"Alice":
+
+@example
+% ./utils/newclient.sh Alice
+Place verifier to peers/6d4ac605ce8dc37c2f0bf21cb542a713/verifier
+@end example
+
+"6d4ac605ce8dc37c2f0bf21cb542a713" -- is the new client's identity.
+
+@strong{Prepare the client}. Generate @ref{Verifier} for known client
+identity:
+
+@example
+% ./utils/storekey.sh /tmp/passphrase
+Enter passphrase:[my secure passphrase is here]
+% govpn-verifier -id 6d4ac605ce8dc37c2f0bf21cb542a713 -key /tmp/passphrase
+562556cc9ecf0019b4cf45bcdf42706944ae9b3ac7c73ad299d83f2d5a169c55
+% rm /tmp/passphrase
+@end example
-As a preparation you have to generate peer directory (register new
-client) on the server side using @code{utils/newsclient.sh}, generate
-@ref{Verifier} on client side and place it on the server. Assume that
-you made those steps.
+"562556cc9ecf0019b4cf45bcdf42706944ae9b3ac7c73ad299d83f2d5a169c55" --
+this is verifier itself.
-GNU/Linux IPv4 client-server example:
+@strong{Save verifier on server}.
@example
-server% echo "echo tap10" >> peers/CLIENTID/up.sh
+% cat > peers/6d4ac605ce8dc37c2f0bf21cb542a713/verifier <<EOF
+562556cc9ecf0019b4cf45bcdf42706944ae9b3ac7c73ad299d83f2d5a169c55
+EOF
+@end example
+
+@strong{Prepare network on GNU/Linux IPv4 server}:
+
+@example
+server% echo "echo tap10" >> peers/6d4ac605ce8dc37c2f0bf21cb542a713/up.sh
server% ip addr add 192.168.0.1/24 dev wlan0
server% tunctl -t tap10
server% ip link set mtu 1432 dev tap10
server% ip addr add 172.16.0.1/24 dev tap10
server% ip link set up dev tap10
-server% GOMAXPROC=4 govpn-server -bind 192.168.0.1:1194 -mtu 1472
@end example
+@strong{Run server daemon itself}:
+
+@example
+server% govpn-server -bind 192.168.0.1:1194 -mtu 1472
+@end example
+
+@strong{Prepare network on GNU/Linux IPv4 client}:
+
@example
client% umask 066
client% utils/storekey.sh key.txt
client% ip addr add 172.16.0.2/24 dev tap10
client% ip link set up dev tap10
client% ip route add default via 172.16.0.1
-client% export GOMAXPROC=4
-client% while :; do
- govpn-client -key key.txt -id CLIENTID -iface tap10 \
- -remote 192.168.0.1:1194 -mtu 1472
-done
@end example
-FreeBSD IPv6 client-server example:
+@strong{Run client daemon itself}:
+@example
+client% govpn-client \
+ -key key.txt \
+ -id 6d4ac605ce8dc37c2f0bf21cb542a713 \
+ -iface tap10 \
+ -remote 192.168.0.1:1194 \
+ -mtu 1472
+@end example
+
+@strong{FreeBSD IPv6 similar client-server example}:
@example
server% ifconfig em0 inet6 fe80::1/64
-server% GOMAXPROC=4 govpn-server -bind "fe80::1%em0"
+server% govpn-server -bind "fe80::1%em0"
@end example
@example
client% ifconfig tap10
client% ifconfig tap10 inet6 fc00::2/96 mtu 1412 up
client% route -6 add default fc00::1
-client% export GOMAXPROC=4
-client% while :; do
- govpn-client -key key.txt -id CLIENTID -iface tap10 \
- -remote [fe80::1%me0]:1194
-done
+client% govpn-client \
+ -key key.txt \
+ -id 6d4ac605ce8dc37c2f0bf21cb542a713 \
+ -iface tap10 \
+ -remote "[fe80::1%me0]":1194
@end example
@emph{govpn-client}, @emph{govpn-server}, @emph{govpn-verifier}
binaries will be build in the current directory.
+As a prerequisite you must install Go compiler and possibly TUN/TAP
+interfaces utilities:
+
+@itemize @bullet
+@item @code{lang/go} port in FreeBSD.
+@item @code{golang} and @code{uml-utilities} packages in GNU/Linux
+distributions.
+@end itemize
+
@example
% wget http://www.cypherpunks.ru/govpn/download/govpn-2.3.tar.xz
% wget http://www.cypherpunks.ru/govpn/download/govpn-2.3.tar.xz.sig
@unnumbered News
@table @strong
+
+@item Release 3.3
+@itemize @bullet
+@item Compatibility with an old GNU Make 3.x. Previously only BSD Make
+and GNU Make 4.x were supported.
+@item /dev/urandom is used for correct client identity generation under
+GNU/Linux systems. Previously /dev/random can produce less than required
+128-bits of random.
+@item Updated user manual examples.
+@end itemize
+
@item Release 3.2
@itemize @bullet
@item
@itemize @bullet
@item Initial stable release.
@end itemize
+
@end table
govpn.MTU = *mtu
- id := govpn.IDDecode(*IDRaw)
- if id == nil {
- panic("ID is not specified")
+ id, err := govpn.IDDecode(*IDRaw)
+ if err != nil {
+ log.Fatalln(err)
}
pub, priv := govpn.NewVerifier(id, govpn.StringFromFile(*keyPath))
bind, err := net.ResolveUDPAddr("udp", "0.0.0.0:0")
if err != nil {
- panic(err)
+ log.Fatalln("Can not resolve address:", err)
}
conn, err := net.ListenUDP("udp", bind)
if err != nil {
- panic(err)
+ log.Fatalln("Can not listen on UDP:", err)
}
remote, err := net.ResolveUDPAddr("udp", *remoteAddr)
if err != nil {
- panic(err)
+ log.Fatalln("Can not resolve remote address:", err)
}
tap, ethSink, ethReady, _, err := govpn.TAPListen(
*cpr,
)
if err != nil {
- panic(err)
+ log.Fatalln("Can not listen on TAP interface:", err)
}
udpSink, udpBuf, udpReady := govpn.ConnListen(conn)
log.Println("Stats are going to listen on", *stats)
statsPort, err := net.Listen("tcp", *stats)
if err != nil {
- panic(err)
+ log.Fatalln("Can not listen on stats port:", err)
}
go govpn.StatsProcessor(statsPort, &knownPeers)
}
bind, err := net.ResolveUDPAddr("udp", *bindAddr)
if err != nil {
- panic(err)
+ log.Fatalln("Can not resolve bind address:", err)
}
conn, err := net.ListenUDP("udp", bind)
if err != nil {
- panic(err)
+ log.Fatalln("Can listen on UDP:", err)
}
udpSink, udpBuf, udpReady := govpn.ConnListen(conn)
log.Println("Stats are going to listen on", *stats)
statsPort, err := net.Listen("tcp", *stats)
if err != nil {
- panic(err)
+ log.Fatalln("Can not listen on stats port:", err)
}
go govpn.StatsProcessor(statsPort, &knownPeers)
}
"encoding/hex"
"flag"
"fmt"
+ "log"
"govpn"
)
func main() {
flag.Parse()
- id := govpn.IDDecode(*IDRaw)
- if id == nil {
- panic("ID is not specified")
+ id, err := govpn.IDDecode(*IDRaw)
+ if err != nil {
+ log.Fatalln(err)
}
pub, _ := govpn.NewVerifier(id, govpn.StringFromFile(*keyPath))
if *verifierPath == "" {
} else {
verifier, err := hex.DecodeString(govpn.StringFromFile(*verifierPath))
if err != nil {
- panic("Can not decode verifier")
+ log.Fatalln("Can not decode verifier:", err)
}
fmt.Println(subtle.ConstantTimeCompare(verifier[:], pub[:]) == 1)
}
reprFound := false
for !reprFound {
if _, err := rand.Read(priv[:]); err != nil {
- panic("Can not read random for DH private key")
+ log.Fatalln("Error reading random for DH private key:", err)
}
reprFound = extra25519.ScalarBaseMult(pub, repr, priv)
}
state.rNonce = new([RSize]byte)
if _, err := rand.Read(state.rNonce[:]); err != nil {
- panic("Can not read random for handshake nonce")
+ log.Fatalln("Error reading random for nonce:", err)
}
enc := make([]byte, 32)
salsa20.XORKeyStream(enc, dhPubRepr[:], state.rNonce[:], state.dsaPubH)
data := append(state.rNonce[:], enc...)
data = append(data, idTag(state.Conf.Id, state.rNonce[:])...)
- if _, err := conn.WriteTo(data, addr); err != nil {
- panic(err)
- }
+ conn.WriteToUDP(data, addr)
return state
}
// Generate R* and encrypt them
h.rServer = new([RSize]byte)
if _, err := rand.Read(h.rServer[:]); err != nil {
- panic("Can not read random for handshake random key")
+ log.Fatalln("Error reading random for R:", err)
}
h.sServer = new([SSize]byte)
if _, err := rand.Read(h.sServer[:]); err != nil {
- panic("Can not read random for handshake shared key")
+ log.Fatalln("Error reading random for S:", err)
}
encRs := make([]byte, RSize+SSize)
salsa20.XORKeyStream(encRs, append(h.rServer[:], h.sServer[:]...), h.rNonce[:], h.key)
// Send that to client
- if _, err := conn.WriteTo(
- append(encPub, append(encRs, idTag(h.Conf.Id, encPub)...)...), h.addr); err != nil {
- panic(err)
- }
+ conn.WriteToUDP(append(encPub, append(encRs, idTag(h.Conf.Id, encPub)...)...), h.addr)
h.LastPing = time.Now()
} else
// ENC(K, R+1, RS + RC + SC + Sign(DSAPriv, K)) + IDtag
// Send final answer to client
enc := make([]byte, RSize)
salsa20.XORKeyStream(enc, dec[RSize:RSize+RSize], h.rNonceNext(2), h.key)
- if _, err := conn.WriteTo(append(enc, idTag(h.Conf.Id, enc)...), h.addr); err != nil {
- panic(err)
- }
+ conn.WriteToUDP(append(enc, idTag(h.Conf.Id, enc)...), h.addr)
// Switch peer
peer := newPeer(
// Generate R* and signature and encrypt them
h.rClient = new([RSize]byte)
if _, err := rand.Read(h.rClient[:]); err != nil {
- panic("Can not read random for handshake random key")
+ log.Fatalln("Error reading random for R:", err)
}
h.sClient = new([SSize]byte)
if _, err := rand.Read(h.sClient[:]); err != nil {
- panic("Can not read random for handshake shared key")
+ log.Fatalln("Error reading random for S:", err)
}
sign := ed25519.Sign(h.Conf.DSAPriv, h.key[:])
append(h.sClient[:], sign[:]...)...)...), h.rNonceNext(1), h.key)
// Send that to server
- if _, err := conn.WriteTo(append(enc, idTag(h.Conf.Id, enc)...), h.addr); err != nil {
- panic(err)
- }
+ conn.WriteToUDP(append(enc, idTag(h.Conf.Id, enc)...), h.addr)
h.LastPing = time.Now()
case 16: // ENC(K, R+2, RC) + IDtag
if h.key == nil {
import (
"crypto/subtle"
"encoding/hex"
+ "errors"
"io/ioutil"
"log"
"os"
}
available := make(map[PeerId]bool)
for _, peerId := range peerIds {
- id := IDDecode(peerId)
- if id == nil {
+ id, err := IDDecode(peerId)
+ if err != nil {
continue
}
available[*id] = true
// Decode identification string.
// It must be 32 hexadecimal characters long.
-// If it is not the valid one, then return nil.
-func IDDecode(raw string) *PeerId {
+func IDDecode(raw string) (*PeerId, error) {
if len(raw) != IDSize*2 {
- return nil
+ return nil, errors.New("ID must be 32 characters long")
}
idDecoded, err := hex.DecodeString(raw)
if err != nil {
- return nil
+ return nil, errors.New("ID must contain hexadecimal characters only")
}
idP := new([IDSize]byte)
copy(idP[:], idDecoded)
id := PeerId(*idP)
- return &id
+ return &id, nil
}
<-tap.ready
n, err = tap.dev.Read(tap.buf)
if err != nil {
- panic(err)
+ panic("Reading TAP:" + err.Error())
}
tap.sink <- tap.buf[:n]
}
func init() {
MTU = 1500
addr, _ = net.ResolveUDPAddr("udp", "[::1]:1")
- peerId = IDDecode("ffffffffffffffffffffffffffffffff")
+ peerId, _ = IDDecode("ffffffffffffffffffffffffffffffff")
conf = &PeerConf{
Id: peerId,
Timeout: time.Second * time.Duration(TimeoutDefault),
"bytes"
"crypto/sha512"
"io/ioutil"
+ "log"
"strings"
"github.com/agl/ed25519"
src := bytes.NewBuffer(r)
pub, priv, err := ed25519.GenerateKey(src)
if err != nil {
- panic("Unable to generate Ed25519 keypair" + err.Error())
+ log.Fatalln("Unable to generate Ed25519 keypair", err)
}
return pub, priv
}
-// Read string from the file, trimming newline. Panics if error occured.
+// Read string from the file, trimming newline.
func StringFromFile(path string) string {
s, err := ioutil.ReadFile(path)
if err != nil {
- panic("Can not read string from" + path)
+ log.Fatalln("Can not read string from", path, err)
}
return strings.TrimRight(string(s), "\n")
}
getrand()
{
local size=$1
- dd if=/dev/random bs=$size count=1 2>/dev/null | hexdump -ve '"%02x"'
+ dd if=/dev/urandom bs=$size count=1 2>/dev/null | hexdump -ve '"%02x"'
}
[ -n "$1" ] || {