[submodule "src/golang.org/x/crypto"]
path = src/golang.org/x/crypto
url = https://go.googlesource.com/crypto
-[submodule "src/github.com/go-yaml/yaml"]
- path = src/github.com/go-yaml/yaml
- url = https://github.com/go-yaml/yaml.git
[submodule "src/cypherpunks.ru/balloon"]
path = src/cypherpunks.ru/balloon
url = git://git.cypherpunks.ru/balloon.git
+[submodule "src/gopkg.in/yaml.v2"]
+ path = src/gopkg.in/yaml.v2
+ url = https://github.com/go-yaml/yaml.git
+ branch = v2
+++ /dev/null
-doc/news.texi
\ No newline at end of file
+++ /dev/null
-doc/news.ru.texi
\ No newline at end of file
-* Applied Cryptography (https://www.schneier.com/books/applied_cryptography/) (C) 1996 Bruce Schneier.
-* Strong Password-Only Authenticated Key Exchange (http://tnlandforms.us/cns05/speke.pdf) (C) 1996 David P. Jablon.
-* Augmented Encrypted Key Exchange (https://www.cs.columbia.edu/~smb/papers/aeke.pdf): a Password-Based Protocol Secure Against Dictionary Attacks and Password File Compromise (C) Steven M. Belloving, Michael Merrit.
-* Watson Ladd <watsonbladd@gmail.com> for suggestion of Elligator (http://elligator.cr.yp.to/) encoding.
-* Password Hashing Competition for Argon2 (https://password-hashing.net/#argon2).
-* Chaffing and Winnowing: Confidentiality without Encryption (http://people.csail.mit.edu/rivest/chaffing-980701.txt) (C) Ronald L. Rivest
-* Zhuoyun Wei <wzyboy@wzyboy.org> for AUR port maintaining and his documentation related fixes.
+* Watson Ladd <watsonbladd at gmail dot com> for suggestion of Elligator encoding.
+* Zhuoyun Wei <wzyboy at wzyboy dot org> for AUR port maintaining and
+ his documentation related fixes.
+* Bruno Clermont <bruno at robotinfra dot com> for finding serious bugs
+ and code refactoring
(or use @url{https://sourceforge.net/projects/govpn/files/, Sourceforge mirror}).
Do not forget to check tarball @ref{Integrity, integrity}.
+Tarballs include all necessary required libraries:
+
+@multitable @columnfractions .40 .20 .40
+@headitem Library @tab Platform @tab Licence
+@item @code{github.com/agl/ed25519} @tab All @tab BSD 3-Clause
+@item @code{github.com/bigeagle/water} @tab GNU/Linux @tab BSD 3-Clause
+@item @code{github.com/go-yaml/yaml} @tab All @tab Apache License 2.0 and MIT
+@item @code{golang.org/x/crypto} @tab All @tab BSD 3-Clause
+@end multitable
+
@multitable {XXXXX} {XXXX KiB} {link sign} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}
@headitem Version @tab Size @tab Tarball @tab SHA256 checksum
+@item @ref{Release 7.0, 7.0} @tab 287 KiB
+@tab @url{download/govpn-7.0.tar.xz, link} @url{download/govpn-7.0.tar.xz.sig, sign}
+@tab @code{DF85E42D F1228E8C FA5D582D AEF90553 23033630 E12B0B26 D7DEFBEB B25DBC4C}
+
@item @ref{Release 6.0, 6.0} @tab 310 KiB
@tab @url{download/govpn-6.0.tar.xz, link} @url{download/govpn-6.0.tar.xz.sig, sign}
@tab @code{3ACAE3B9 884F3260 38FCA9CE 6A309DF6 71BE6386 1FB2058B C79AE7DC 2A1A1811}
daemon, aimed to be reviewable, secure, DPI/censorship-resistant,
written on Go.
-Copyright @copyright{} 2014-2016 @email{stargrave@@stargrave.org, Sergey Matveev}
+Copyright @copyright{} 2014-2017 @email{stargrave@@stargrave.org, Sergey Matveev}
@quotation
Permission is granted to copy, distribute and/or modify this document
@url{https://www.gnu.org/software/texinfo/, Texinfo} (6.1+ version is
recommended) is used for building documentation. Possibly you also need
to install TUN/TAP interface utilities (depending on your operating
-system): @code{uml-utilities} package in most GNU/Linux distributions.
-
-Included required libraries:
-
-@multitable @columnfractions .40 .20 .40
-@headitem Library @tab Platform @tab Licence
-@item @code{github.com/agl/ed25519} @tab All @tab BSD 3-Clause
-@item @code{github.com/bigeagle/water} @tab GNU/Linux @tab BSD 3-Clause
-@item @code{github.com/go-yaml/yaml} @tab All @tab LGPLv3 and MIT
-@item @code{golang.org/x/crypto} @tab All @tab BSD 3-Clause
-@end multitable
+system): @command{uml-utilities} package in most GNU/Linux distributions.
Get @ref{Tarballs, the tarball}, check its
@ref{Integrity, integrity and authenticity} and run @command{make}.
% make -C govpn-2.3 all
@end verbatim
-There is @code{install} target respecting @env{DESTDIR}. It will
-install binaries, info-documentation and utilities.
+There is @command{install} target respecting @env{DESTDIR}.
+It will install binaries, info-documentation and utilities.
@menu
* Prepared tarballs: Tarballs.
@node Integrity
@section Tarballs integrity check
-You @strong{have to} verify downloaded archives integrity and check
+You @strong{have to} check downloaded archives integrity and verify
their signature to be sure that you have got trusted, untampered
software. For integrity and authentication of downloaded binaries
@url{https://www.gnupg.org/, The GNU Privacy Guard} is used. You must
@node Новости
@section Новости
+@node Релиз 7.1
+@subsection Релиз 7.1
+@itemize
+@item Исправлена ошибка в коде генерирования и определения идентификации
+клиента: параллельно работающие клиенты могут быть неправильно
+определены, не давая возможности их подсоединения и позволяя DPI
+выявлять GoVPN пакеты.
+@end itemize
+
@node Релиз 7.0
@subsection Релиз 7.0
@itemize
@node Релиз 5.4
@subsection Релиз 5.4
@itemize
-@item Добавлена возможность требования @ref{Timesync, синхронизации
-времени}. Она добавит временные метки в PRP аутентификацию сообщений
+@item Добавлена возможность требования синхронизации
+времени. Она добавит временные метки в PRP аутентификацию сообщений
рукопожатия, не позволяя повторить ранее перехваченные пакеты и получить
ответ от сервера, делая его видимым для DPI.
@end itemize
@subsection Релиз 5.0
@itemize
-@item Новый опциональный @ref{Encless, нешифрованный режим} работы.
+@item Новый опциональный нешифрованный режим работы.
Технически к исходящим пакетам не применяются функции шифрования,
поэтому вас не могут вынудить выдать ключи шифрования или привлечь к
ответственности за использования шифрования.
-@item @ref{MTU} конфигурируются относительно каждого пользователя отдельно.
+@item MTU конфигурируются относительно каждого пользователя отдельно.
@item Упрощённая схема дополнения полезной нагрузки, экономия в один байт.
@item Возможность указать название TAP интерфейса явно, без
использования up-скриптов.
-@item @command{govpn-verifier} утилита теперь может использовать @ref{EGD}.
+@item @command{govpn-verifier} утилита теперь может использовать EGD.
@end itemize
@node Релиз 4.2
@node Релиз 3.5
@subsection Релиз 3.5
@itemize
-@item Возможность использовать @ref{Network, TCP} сетевой транспорт.
+@item Возможность использовать TCP сетевой транспорт.
Сервер можно слушать одновременно на UDP и TCP сокетах.
-@item Возможность использовать @ref{Proxy, HTTP прокси} (через CONNECT
+@item Возможность использовать HTTP прокси (через CONNECT
метод) для доступа к серверу. Сервер может эмулировать поведение HTTP
прокси.
@item Обновлённая Poly1305 библиотека с исправлениями для ARM.
@node Релиз 3.4
@subsection Релиз 3.4
@itemize
-@item Возможность использовать внешний @ref{EGD} совместимый PRNG.
+@item Возможность использовать внешний EGD совместимый PRNG.
Теперь вы можете использовать GoVPN даже на системах с плохим
@file{/dev/random}.
@item Опция @option{-noncediff} удалена. Она заменена на хранилище уже
@itemize
@item Поддержка FreeBSD.
@end itemize
-
-@node Релиз 1.0
-@subsection Релиз 1.0
-@itemize
-@item Первый стабильный релиз.
-@end itemize
See also this page @ref{Новости, on russian}.
+@node Release 7.1
+@section Release 7.1
+@itemize
+@item Fixed bug in client's identity generation and detection code:
+simultaneous clients may be incorrectly identified, preventing their
+connection establishing and allowing DPI to detect GoVPN packets.
+@end itemize
+
@node Release 7.0
@section Release 7.0
@itemize
@node Release 5.4
@section Release 5.4
@itemize
-@item Added optional @ref{Timesync, time synchronization} requirement.
+@item Added optional time synchronization requirement.
It will add timestamps in handshake PRP authentication, disallowing to
repeat captured packet and get reply from the server, making it visible
to DPI.
@node Release 5.0
@section Release 5.0
@itemize
-@item New optional @ref{Encless, encryptionless mode} of operation.
+@item New optional encryptionless mode of operation.
Technically no encryption functions are applied for outgoing packets, so
you can not be forced to reveal your encryption keys or sued for
encryption usage.
-@item @ref{MTU}s are configured on per-user basis.
+@item MTUs are configured on per-user basis.
@item Simplified payload padding scheme, saving one byte of data.
@item Ability to specify TAP interface name explicitly without any
up-scripts for convenience.
-@item @command{govpn-verifier} utility also can use @ref{EGD}.
+@item @command{govpn-verifier} utility also can use EGD.
@end itemize
@node Release 4.2
@node Release 3.5
@section Release 3.5
@itemize
-@item Ability to use @ref{Network, TCP} network transport.
+@item Ability to use TCP network transport.
Server can listen on both UDP and TCP sockets.
-@item Ability to use @ref{Proxy, HTTP proxies} (through CONNECT method)
+@item Ability to use HTTP proxies (through CONNECT method)
for accessing the server. Server can also emulate HTTP proxy behaviour.
@item Updated Poly1305 library with ARM-related bugfixes.
@item Go 1.5+ version is highly recommended because of performance
@node Release 3.4
@section Release 3.4
@itemize
-@item Ability to use external @ref{EGD}-compatible PRNGs. Now you are
+@item Ability to use external EGD-compatible PRNGs. Now you are
able to use GoVPN even on systems with the bad @file{/dev/random},
providing higher quality entropy from external sources.
@item Removed @option{-noncediff} option. It is replaced with in-memory
@itemize
@item FreeBSD support.
@end itemize
-
-@node Release 1.0
-@section Release 1.0
-@itemize
-@item Initial stable release.
-@end itemize
Development source code contains the latest version of the code. It may
be buggy. It does not contain compiled documentation and dependent
-libraries source code. Because of that, it is not recommended for
-porters: use @ref{Tarballs} instead.
+libraries source code. Because of that, it is recommended for porters
+to use @ref{Tarballs, tarballs} instead.
You can obtain it by cloning @url{http://git-scm.com/, Git}
@url{http://git.cypherpunks.ru/cgit.cgi/govpn.git/log/, repository}
Thanks for contributions and suggestions to:
@itemize
-@item @url{https://www.schneier.com/books/applied_cryptography/, Applied Cryptography} @copyright{} 1996 Bruce Schneier.
-@item @url{http://tnlandforms.us/cns05/speke.pdf, Strong Password-Only Authenticated Key Exchange} @copyright{} 1996 David P. Jablon.
-@item @url{https://www.cs.columbia.edu/~smb/papers/aeke.pdf, Augmented Encrypted Key Exchange}: a Password-Based Protocol Secure Against Dictionary Attacks and Password File Compromise @copyright{} Steven M. Belloving, Michael Merrit.
-@item @email{watsonbladd@@gmail.com, Watson Ladd} for suggestion of @url{http://elligator.cr.yp.to/, Elligator} encoding.
-@item @url{https://password-hashing.net/#argon2, Password Hashing Competition for Argon2}.
-@item @url{https://crypto.stanford.edu/balloon/, Balloon hashing}.
-@item @url{http://people.csail.mit.edu/rivest/chaffing-980701.txt, Chaffing and Winnowing: Confidentiality without Encryption} @copyright{} Ronald L. Rivest
-@item @email{wzyboy@@wzyboy.org, Zhuoyun Wei} for @url{https://aur.archlinux.org/packages/govpn/, AUR} port maintaining and his documentation related fixes.
+@item Watson Ladd for suggestion of @url{http://elligator.cr.yp.to/, Elligator} encoding.
+@item Zhuoyun Wei for @url{https://aur.archlinux.org/packages/govpn/, AUR} port
+maintaining and his documentation related fixes.
+@item Bruno Clermont for finding serious bugs and code refactoring.
@end itemize
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
)
var (
- testKey *[16]byte = new([16]byte)
+ testKey = new([16]byte)
)
func init() {
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
)
var (
- dummyNonce *[16]byte = new([16]byte)
+ dummyNonce = new([16]byte)
)
// Encode the data, produce AONT package. Data size will be larger than
--- /dev/null
+/*
+GoVPN -- simple secure free software virtual private network daemon
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package client
+
+import (
+ "errors"
+ "fmt"
+ "net"
+ "os"
+ "time"
+
+ "github.com/agl/ed25519"
+
+ "cypherpunks.ru/govpn"
+)
+
+type Protocol int
+
+const (
+ ProtocolUDP Protocol = iota
+ ProtocolTCP
+)
+
+type Configuration struct {
+ PrivateKey *[ed25519.PrivateKeySize]byte
+ Peer *govpn.PeerConf
+ Protocol Protocol
+ InterfaceName string
+ ProxyAddress string
+ ProxyAuthentication string
+ RemoteAddress string
+ UpPath string
+ DownPath string
+ StatsAddress string
+ NoReconnect bool
+ MTU int
+}
+
+func (c *Configuration) Validate() error {
+ if c.MTU > govpn.MTUMax {
+ return fmt.Errorf("Invalid MTU %d, maximum allowable is %d", c.MTU, govpn.MTUMax)
+ }
+ if len(c.RemoteAddress) == 0 {
+ return errors.New("Missing RemoteAddress")
+ }
+ if len(c.InterfaceName) == 0 {
+ return errors.New("Missing InterfaceName")
+ }
+ return nil
+}
+
+func (c *Configuration) isProxy() bool {
+ return len(c.ProxyAddress) > 0
+}
+
+type Client struct {
+ idsCache *govpn.MACCache
+ tap *govpn.TAP
+ knownPeers govpn.KnownPeers
+ statsPort net.Listener
+ timeouted chan struct{}
+ rehandshaking chan struct{}
+ termination chan struct{}
+ firstUpCall bool
+ termSignal chan os.Signal
+ config Configuration
+
+ // Error channel receives any kind of routine errors
+ Error chan error
+}
+
+func (c *Client) MainCycle() {
+ var err error
+ c.tap, err = govpn.TAPListen(c.config.InterfaceName, c.config.MTU)
+ if err != nil {
+ c.Error <- fmt.Errorf("Can not listen on TUN/TAP interface: %s", err.Error())
+ return
+ }
+
+ if len(c.config.StatsAddress) > 0 {
+ c.statsPort, err = net.Listen("tcp", c.config.StatsAddress)
+ if err != nil {
+ c.Error <- fmt.Errorf("Can't listen on stats port: %s", err.Error())
+ return
+ }
+ c.knownPeers = govpn.KnownPeers(make(map[string]**govpn.Peer))
+ go govpn.StatsProcessor(c.statsPort, &c.knownPeers)
+ }
+
+MainCycle:
+ for {
+ c.timeouted = make(chan struct{})
+ c.rehandshaking = make(chan struct{})
+ c.termination = make(chan struct{})
+ switch c.config.Protocol {
+ case ProtocolUDP:
+ go c.startUDP()
+ case ProtocolTCP:
+ if c.config.isProxy() {
+ go c.proxyTCP()
+ } else {
+ go c.startTCP()
+ }
+ }
+ select {
+ case <-c.termSignal:
+ govpn.BothPrintf(`[finish remote="%s"]`, c.config.RemoteAddress)
+ c.termination <- struct{}{}
+ // empty value signals that everything is fine
+ c.Error <- nil
+ break MainCycle
+ case <-c.timeouted:
+ if c.config.NoReconnect {
+ break MainCycle
+ }
+ govpn.BothPrintf(`[sleep seconds="%d"]`, c.config.Peer.Timeout/time.Second)
+ time.Sleep(c.config.Peer.Timeout)
+ case <-c.rehandshaking:
+ }
+ close(c.timeouted)
+ close(c.rehandshaking)
+ close(c.termination)
+ }
+ if _, err = govpn.ScriptCall(
+ c.config.DownPath,
+ c.config.InterfaceName,
+ c.config.RemoteAddress,
+ ); err != nil {
+ c.Error <- err
+ }
+}
+
+func NewClient(conf Configuration, verifier *govpn.Verifier, termSignal chan os.Signal) *Client {
+ client := Client{
+ idsCache: govpn.NewMACCache(),
+ firstUpCall: true,
+ config: conf,
+ termSignal: termSignal,
+ Error: make(chan error, 1),
+ }
+ confs := map[govpn.PeerID]*govpn.PeerConf{*verifier.ID: conf.Peer}
+ client.idsCache.Update(&confs)
+ return &client
+}
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package main
+package client
import (
"bufio"
"encoding/base64"
- "log"
+ "fmt"
"net"
"net/http"
"cypherpunks.ru/govpn"
)
-func proxyTCP(timeouted, rehandshaking, termination chan struct{}) {
- proxyAddr, err := net.ResolveTCPAddr("tcp", *proxyAddr)
+func (c *Client) proxyTCP() {
+ proxyAddr, err := net.ResolveTCPAddr("tcp", c.config.ProxyAddress)
if err != nil {
- log.Fatalln("Can not resolve proxy address:", err)
+ c.Error <- err
+ return
}
conn, err := net.DialTCP("tcp", nil, proxyAddr)
if err != nil {
- log.Fatalln("Can not connect to proxy:", err)
+ c.Error <- err
+ return
}
- req := "CONNECT " + *remoteAddr + " HTTP/1.1\n"
- req += "Host: " + *remoteAddr + "\n"
- if *proxyAuth != "" {
+ req := "CONNECT " + c.config.ProxyAddress + " HTTP/1.1\n"
+ req += "Host: " + c.config.ProxyAddress + "\n"
+ if c.config.ProxyAuthentication != "" {
req += "Proxy-Authorization: Basic "
- req += base64.StdEncoding.EncodeToString([]byte(*proxyAuth)) + "\n"
+ req += base64.StdEncoding.EncodeToString([]byte(c.config.ProxyAuthentication)) + "\n"
}
req += "\n"
conn.Write([]byte(req))
&http.Request{Method: "CONNECT"},
)
if err != nil || resp.StatusCode != http.StatusOK {
- log.Fatalln("Unexpected response from proxy")
+ c.Error <- fmt.Errorf("Unexpected response from proxy: %s", err.Error())
+ return
}
- govpn.Printf(`[proxy-connected remote="%s" addr="%s"]`, *remoteAddr, *proxyAddr)
- go handleTCP(conn, timeouted, rehandshaking, termination)
+ govpn.Printf(`[proxy-connected remote="%s" addr="%s"]`, c.config.RemoteAddress, *proxyAddr)
+ go c.handleTCP(conn)
}
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package main
+package client
import (
"bytes"
- "log"
+ "fmt"
"net"
"sync/atomic"
"time"
"cypherpunks.ru/govpn"
)
-func startTCP(timeouted, rehandshaking, termination chan struct{}) {
- remote, err := net.ResolveTCPAddr("tcp", *remoteAddr)
+func (c *Client) startTCP() {
+ remote, err := net.ResolveTCPAddr("tcp", c.config.RemoteAddress)
if err != nil {
- log.Fatalln("Can not resolve remote address:", err)
+ c.Error <- fmt.Errorf("Can not resolve remote address: %s", err)
+ return
}
conn, err := net.DialTCP("tcp", nil, remote)
if err != nil {
- log.Fatalln("Can not connect to address:", err)
+ c.Error <- fmt.Errorf("Can not connect to address: %s", err)
+ return
}
- govpn.Printf(`[connected remote="%s"]`, *remoteAddr)
- handleTCP(conn, timeouted, rehandshaking, termination)
+ govpn.Printf(`[connected remote="%s"]`, c.config.RemoteAddress)
+ c.handleTCP(conn)
}
-func handleTCP(conn *net.TCPConn, timeouted, rehandshaking, termination chan struct{}) {
- hs := govpn.HandshakeStart(*remoteAddr, conn, conf)
- buf := make([]byte, 2*(govpn.EnclessEnlargeSize+*mtu)+*mtu)
+func (c *Client) handleTCP(conn *net.TCPConn) {
+ hs := govpn.HandshakeStart(c.config.RemoteAddress, conn, c.config.Peer)
+ buf := make([]byte, 2*(govpn.EnclessEnlargeSize+c.config.MTU)+c.config.MTU)
var n int
var err error
var prev int
HandshakeCycle:
for {
select {
- case <-termination:
+ case <-c.termination:
break HandshakeCycle
default:
}
if prev == len(buf) {
- govpn.Printf(`[packet-timeouted remote="%s"]`, *remoteAddr)
- timeouted <- struct{}{}
+ govpn.Printf(`[packet-timeouted remote="%s"]`, c.config.RemoteAddress)
+ c.timeouted <- struct{}{}
break HandshakeCycle
}
- conn.SetReadDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
+ if err = conn.SetReadDeadline(time.Now().Add(c.config.Peer.Timeout)); err != nil {
+ c.Error <- err
+ break HandshakeCycle
+ }
n, err = conn.Read(buf[prev:])
if err != nil {
- govpn.Printf(`[connection-timeouted remote="%s"]`, *remoteAddr)
- timeouted <- struct{}{}
+ govpn.Printf(`[connection-timeouted remote="%s"]`, c.config.RemoteAddress)
+ c.timeouted <- struct{}{}
break HandshakeCycle
}
prev += n
- peerId := idsCache.Find(buf[:prev])
- if peerId == nil {
+ peerID := c.idsCache.Find(buf[:prev])
+ if peerID == nil {
continue
}
peer = hs.Client(buf[:prev])
if peer == nil {
continue
}
- govpn.Printf(`[handshake-completed remote="%s"]`, *remoteAddr)
- knownPeers = govpn.KnownPeers(map[string]**govpn.Peer{*remoteAddr: &peer})
- if firstUpCall {
- go govpn.ScriptCall(*upPath, *ifaceName, *remoteAddr)
- firstUpCall = false
+ govpn.Printf(`[handshake-completed remote="%s"]`, c.config.RemoteAddress)
+ c.knownPeers = govpn.KnownPeers(map[string]**govpn.Peer{c.config.RemoteAddress: &peer})
+ if c.firstUpCall {
+ go govpn.ScriptCall(c.config.UpPath, c.config.InterfaceName, c.config.RemoteAddress)
+ c.firstUpCall = false
}
hs.Zero()
terminator = make(chan struct{})
- go govpn.PeerTapProcessor(peer, tap, terminator)
+ go govpn.PeerTapProcessor(peer, c.tap, terminator)
break HandshakeCycle
}
if hs != nil {
TransportCycle:
for {
select {
- case <-termination:
+ case <-c.termination:
break TransportCycle
default:
}
if prev == len(buf) {
- govpn.Printf(`[packet-timeouted remote="%s"]`, *remoteAddr)
- timeouted <- struct{}{}
+ govpn.Printf(`[packet-timeouted remote="%s"]`, c.config.RemoteAddress)
+ c.timeouted <- struct{}{}
+ break TransportCycle
+ }
+ if err = conn.SetReadDeadline(time.Now().Add(c.config.Peer.Timeout)); err != nil {
+ c.Error <- err
break TransportCycle
}
- conn.SetReadDeadline(time.Now().Add(time.Duration(timeout) * time.Second))
n, err = conn.Read(buf[prev:])
if err != nil {
- govpn.Printf(`[connection-timeouted remote="%s"]`, *remoteAddr)
- timeouted <- struct{}{}
+ govpn.Printf(`[connection-timeouted remote="%s"]`, c.config.RemoteAddress)
+ c.timeouted <- struct{}{}
break TransportCycle
}
prev += n
if i == -1 {
continue
}
- if !peer.PktProcess(buf[:i+govpn.NonceSize], tap, false) {
- govpn.Printf(`[packet-unauthenticated remote="%s"]`, *remoteAddr)
- timeouted <- struct{}{}
+ if !peer.PktProcess(buf[:i+govpn.NonceSize], c.tap, false) {
+ govpn.Printf(`[packet-unauthenticated remote="%s"]`, c.config.RemoteAddress)
+ c.timeouted <- struct{}{}
break TransportCycle
}
if atomic.LoadUint64(&peer.BytesIn)+atomic.LoadUint64(&peer.BytesOut) > govpn.MaxBytesPerKey {
- govpn.Printf(`[rehandshake-required remote="%s"]`, *remoteAddr)
- rehandshaking <- struct{}{}
+ govpn.Printf(`[rehandshake-required remote="%s"]`, c.config.RemoteAddress)
+ c.rehandshaking <- struct{}{}
break TransportCycle
}
copy(buf, buf[i+govpn.NonceSize:prev])
terminator <- struct{}{}
}
peer.Zero()
- conn.Close()
+ if err = conn.Close(); err != nil {
+ c.Error <- err
+ }
}
--- /dev/null
+/*
+GoVPN -- simple secure free software virtual private network daemon
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package client
+
+import (
+ "fmt"
+ "net"
+ "sync/atomic"
+ "time"
+
+ "cypherpunks.ru/govpn"
+)
+
+func (c *Client) startUDP() {
+ remote, err := net.ResolveUDPAddr("udp", c.config.RemoteAddress)
+ if err != nil {
+ c.Error <- fmt.Errorf("Can not resolve remote address: %s", err)
+ return
+ }
+ conn, err := net.DialUDP("udp", nil, remote)
+ if err != nil {
+ c.Error <- fmt.Errorf("Can not connect remote address: %s", err)
+ return
+ }
+ govpn.Printf(`[connected remote="%s"]`, c.config.RemoteAddress)
+
+ hs := govpn.HandshakeStart(c.config.RemoteAddress, conn, c.config.Peer)
+ buf := make([]byte, c.config.MTU*2)
+ var n int
+ var timeouts int
+ var peer *govpn.Peer
+ var terminator chan struct{}
+ timeout := int(c.config.Peer.Timeout.Seconds())
+MainCycle:
+ for {
+ select {
+ case <-c.termination:
+ break MainCycle
+ default:
+ }
+
+ if err = conn.SetReadDeadline(time.Now().Add(time.Second)); err != nil {
+ c.Error <- err
+ break MainCycle
+ }
+ n, err = conn.Read(buf)
+ if timeouts == timeout {
+ govpn.Printf(`[connection-timeouted remote="%s"]`, c.config.RemoteAddress)
+ c.timeouted <- struct{}{}
+ break
+ }
+ if err != nil {
+ timeouts++
+ continue
+ }
+ if peer != nil {
+ if peer.PktProcess(buf[:n], c.tap, true) {
+ timeouts = 0
+ } else {
+ govpn.Printf(`[packet-unauthenticated remote="%s"]`, c.config.RemoteAddress)
+ timeouts++
+ }
+ if atomic.LoadUint64(&peer.BytesIn)+atomic.LoadUint64(&peer.BytesOut) > govpn.MaxBytesPerKey {
+ govpn.Printf(`[rehandshake-required remote="%s"]`, c.config.RemoteAddress)
+ c.rehandshaking <- struct{}{}
+ break MainCycle
+ }
+ continue
+ }
+ if c.idsCache.Find(buf[:n]) == nil {
+ govpn.Printf(`[identity-invalid remote="%s"]`, c.config.RemoteAddress)
+ continue
+ }
+ timeouts = 0
+ peer = hs.Client(buf[:n])
+ if peer == nil {
+ continue
+ }
+ govpn.Printf(`[handshake-completed remote="%s"]`, c.config.RemoteAddress)
+ c.knownPeers = govpn.KnownPeers(map[string]**govpn.Peer{c.config.RemoteAddress: &peer})
+ if c.firstUpCall {
+ go govpn.ScriptCall(c.config.UpPath, c.config.InterfaceName, c.config.RemoteAddress)
+ c.firstUpCall = false
+ }
+ hs.Zero()
+ terminator = make(chan struct{})
+ go govpn.PeerTapProcessor(peer, c.tap, terminator)
+ }
+ if terminator != nil {
+ terminator <- struct{}{}
+ }
+ if hs != nil {
+ hs.Zero()
+ }
+ if err = conn.Close(); err != nil {
+ c.Error <- err
+ }
+}
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
"flag"
"fmt"
"log"
- "net"
"os"
"os/signal"
"time"
"cypherpunks.ru/govpn"
-)
-
-var (
- remoteAddr = flag.String("remote", "", "Remote server address")
- proto = flag.String("proto", "udp", "Protocol to use: udp or tcp")
- ifaceName = flag.String("iface", "tap0", "TUN/TAP network interface")
- verifierRaw = flag.String("verifier", "", "Verifier")
- keyPath = flag.String("key", "", "Path to passphrase file")
- upPath = flag.String("up", "", "Path to up-script")
- downPath = flag.String("down", "", "Path to down-script")
- stats = flag.String("stats", "", "Enable stats retrieving on host:port")
- proxyAddr = flag.String("proxy", "", "Use HTTP proxy on host:port")
- proxyAuth = flag.String("proxy-auth", "", "user:password Basic proxy auth")
- mtu = flag.Int("mtu", govpn.MTUDefault, "MTU of TUN/TAP interface")
- timeoutP = flag.Int("timeout", 60, "Timeout seconds")
- timeSync = flag.Int("timesync", 0, "Time synchronization requirement")
- noreconnect = flag.Bool("noreconnect", false, "Disable reconnection after timeout")
- noisy = flag.Bool("noise", false, "Enable noise appending")
- encless = flag.Bool("encless", false, "Encryptionless mode")
- cpr = flag.Int("cpr", 0, "Enable constant KiB/sec out traffic rate")
- egdPath = flag.String("egd", "", "Optional path to EGD socket")
- syslog = flag.Bool("syslog", false, "Enable logging to syslog")
- version = flag.Bool("version", false, "Print version information")
- warranty = flag.Bool("warranty", false, "Print warranty information")
-
- conf *govpn.PeerConf
- tap *govpn.TAP
- timeout int
- firstUpCall bool = true
- knownPeers govpn.KnownPeers
- idsCache *govpn.MACCache
+ "cypherpunks.ru/govpn/client"
)
func main() {
+ var (
+ remoteAddr = flag.String("remote", "", "Remote server address")
+ proto = flag.String("proto", "udp", "Protocol to use: udp or tcp")
+ ifaceName = flag.String("iface", "tap0", "TUN/TAP network interface")
+ verifierRaw = flag.String("verifier", "", "Verifier")
+ keyPath = flag.String("key", "", "Path to passphrase file")
+ upPath = flag.String("up", "", "Path to up-script")
+ downPath = flag.String("down", "", "Path to down-script")
+ stats = flag.String("stats", "", "Enable stats retrieving on host:port")
+ proxyAddr = flag.String("proxy", "", "Use HTTP proxy on host:port")
+ proxyAuth = flag.String("proxy-auth", "", "user:password Basic proxy auth")
+ mtu = flag.Int("mtu", govpn.MTUDefault, "MTU of TUN/TAP interface")
+ timeoutP = flag.Int("timeout", 60, "Timeout seconds")
+ timeSync = flag.Int("timesync", 0, "Time synchronization requirement")
+ noreconnect = flag.Bool("noreconnect", false, "Disable reconnection after timeout")
+ noisy = flag.Bool("noise", false, "Enable noise appending")
+ encless = flag.Bool("encless", false, "Encryptionless mode")
+ cpr = flag.Int("cpr", 0, "Enable constant KiB/sec out traffic rate")
+ egdPath = flag.String("egd", "", "Optional path to EGD socket")
+ syslog = flag.Bool("syslog", false, "Enable logging to syslog")
+ version = flag.Bool("version", false, "Print version information")
+ warranty = flag.Bool("warranty", false, "Print warranty information")
+ protocol client.Protocol
+ err error
+ )
+
flag.Parse()
if *warranty {
fmt.Println(govpn.Warranty)
fmt.Println(govpn.VersionGet())
return
}
- timeout = *timeoutP
- var err error
log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
- if *mtu > govpn.MTUMax {
- log.Fatalln("Maximum allowable MTU is", govpn.MTUMax)
- }
if *egdPath != "" {
log.Println("Using", *egdPath, "EGD")
govpn.EGDInit(*egdPath)
}
- if *proxyAddr != "" {
- *proto = "tcp"
- }
- if !(*proto == "udp" || *proto == "tcp") {
+ switch *proto {
+ case "udp":
+ protocol = client.ProtocolUDP
+ case "tcp":
+ protocol = client.ProtocolTCP
+ default:
log.Fatalln("Unknown protocol specified")
}
+
+ if *proxyAddr != "" && protocol == client.ProtocolUDP {
+ log.Fatalln("HTTP proxy is supported only in TCP mode")
+ }
+
if *verifierRaw == "" {
- log.Fatalln("No verifier specified")
+ log.Fatalln("-verifier is required")
}
verifier, err := govpn.VerifierFromString(*verifierRaw)
if err != nil {
- log.Fatalln(err)
+ log.Fatalln("Invalid -verifier:", err)
}
key, err := govpn.KeyRead(*keyPath)
if err != nil {
- log.Fatalln("Unable to read the key", err)
+ log.Fatalln("Invalid -key:", err)
}
priv := verifier.PasswordApply(key)
if *encless {
- if *proto != "tcp" {
+ if protocol != client.ProtocolTCP {
log.Fatalln("Currently encryptionless mode works only with TCP")
}
*noisy = true
}
- conf = &govpn.PeerConf{
- Id: verifier.Id,
- Iface: *ifaceName,
- MTU: *mtu,
- Timeout: time.Second * time.Duration(timeout),
- TimeSync: *timeSync,
- Noise: *noisy,
- CPR: *cpr,
- Encless: *encless,
- Verifier: verifier,
- DSAPriv: priv,
+ conf := client.Configuration{
+ PrivateKey: priv,
+ Peer: &govpn.PeerConf{
+ ID: verifier.ID,
+ Iface: *ifaceName,
+ MTU: *mtu,
+ Timeout: time.Second * time.Duration(*timeoutP),
+ TimeSync: *timeSync,
+ Noise: *noisy,
+ CPR: *cpr,
+ Encless: *encless,
+ Verifier: verifier,
+ DSAPriv: priv,
+ },
+ Protocol: protocol,
+ InterfaceName: *ifaceName,
+ ProxyAddress: *proxyAddr,
+ ProxyAuthentication: *proxyAuth,
+ RemoteAddress: *remoteAddr,
+ UpPath: *upPath,
+ DownPath: *downPath,
+ StatsAddress: *stats,
+ NoReconnect: *noreconnect,
+ MTU: *mtu,
}
- idsCache = govpn.NewMACCache()
- confs := map[govpn.PeerId]*govpn.PeerConf{*verifier.Id: conf}
- idsCache.Update(&confs)
- log.Println(govpn.VersionGet())
-
- tap, err = govpn.TAPListen(*ifaceName, *mtu)
- if err != nil {
- log.Fatalln("Can not listen on TUN/TAP interface:", err)
+ if err = conf.Validate(); err != nil {
+ log.Fatalln("Invalid settings:", err)
}
- if *stats != "" {
- log.Println("Stats are going to listen on", *stats)
- statsPort, err := net.Listen("tcp", *stats)
- if err != nil {
- log.Fatalln("Can not listen on stats port:", err)
- }
- go govpn.StatsProcessor(statsPort, &knownPeers)
- }
+ log.Println(govpn.VersionGet())
if *syslog {
govpn.SyslogEnable()
termSignal := make(chan os.Signal, 1)
signal.Notify(termSignal, os.Interrupt, os.Kill)
-
-MainCycle:
- for {
- timeouted := make(chan struct{})
- rehandshaking := make(chan struct{})
- termination := make(chan struct{})
- switch *proto {
- case "udp":
- go startUDP(timeouted, rehandshaking, termination)
- case "tcp":
- if *proxyAddr != "" {
- go proxyTCP(timeouted, rehandshaking, termination)
- } else {
- go startTCP(timeouted, rehandshaking, termination)
- }
- }
- select {
- case <-termSignal:
- govpn.BothPrintf(`[finish remote="%s"]`, *remoteAddr)
- termination <- struct{}{}
- break MainCycle
- case <-timeouted:
- if *noreconnect {
- break MainCycle
- }
- govpn.BothPrintf(`[sleep seconds="%d"]`, timeout)
- time.Sleep(time.Second * time.Duration(timeout))
- case <-rehandshaking:
- }
- close(timeouted)
- close(rehandshaking)
- close(termination)
+ c := client.NewClient(conf, verifier, termSignal)
+ go c.MainCycle()
+ if err = <-c.Error; err != nil {
+ log.Fatalln(err)
}
- govpn.ScriptCall(*downPath, *ifaceName, *remoteAddr)
}
+++ /dev/null
-/*
-GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-package main
-
-import (
- "log"
- "net"
- "sync/atomic"
- "time"
-
- "cypherpunks.ru/govpn"
-)
-
-func startUDP(timeouted, rehandshaking, termination chan struct{}) {
- remote, err := net.ResolveUDPAddr("udp", *remoteAddr)
- if err != nil {
- log.Fatalln("Can not resolve remote address:", err)
- }
- conn, err := net.DialUDP("udp", nil, remote)
- if err != nil {
- log.Fatalln("Can not listen on UDP:", err)
- }
- govpn.Printf(`[connected remote="%s"]`, *remoteAddr)
-
- hs := govpn.HandshakeStart(*remoteAddr, conn, conf)
- buf := make([]byte, *mtu*2)
- var n int
- var timeouts int
- var peer *govpn.Peer
- var terminator chan struct{}
-MainCycle:
- for {
- select {
- case <-termination:
- break MainCycle
- default:
- }
-
- conn.SetReadDeadline(time.Now().Add(time.Second))
- n, err = conn.Read(buf)
- if timeouts == timeout {
- govpn.Printf(`[connection-timeouted remote="%s"]`, *remoteAddr)
- timeouted <- struct{}{}
- break
- }
- if err != nil {
- timeouts++
- continue
- }
- if peer != nil {
- if peer.PktProcess(buf[:n], tap, true) {
- timeouts = 0
- } else {
- govpn.Printf(`[packet-unauthenticated remote="%s"]`, *remoteAddr)
- timeouts++
- }
- if atomic.LoadUint64(&peer.BytesIn)+atomic.LoadUint64(&peer.BytesOut) > govpn.MaxBytesPerKey {
- govpn.Printf(`[rehandshake-required remote="%s"]`, *remoteAddr)
- rehandshaking <- struct{}{}
- break MainCycle
- }
- continue
- }
- if idsCache.Find(buf[:n]) == nil {
- govpn.Printf(`[identity-invalid remote="%s"]`, *remoteAddr)
- continue
- }
- timeouts = 0
- peer = hs.Client(buf[:n])
- if peer == nil {
- continue
- }
- govpn.Printf(`[handshake-completed remote="%s"]`, *remoteAddr)
- knownPeers = govpn.KnownPeers(map[string]**govpn.Peer{*remoteAddr: &peer})
- if firstUpCall {
- go govpn.ScriptCall(*upPath, *ifaceName, *remoteAddr)
- firstUpCall = false
- }
- hs.Zero()
- terminator = make(chan struct{})
- go govpn.PeerTapProcessor(peer, tap, terminator)
- }
- if terminator != nil {
- terminator <- struct{}{}
- }
- if hs != nil {
- hs.Zero()
- }
- conn.Close()
-}
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
handshakes map[string]*govpn.Handshake = make(map[string]*govpn.Handshake)
hsLock sync.RWMutex
- peers map[string]*PeerState = make(map[string]*PeerState)
+ peers = make(map[string]*PeerState)
peersLock sync.RWMutex
- peersById map[govpn.PeerId]string = make(map[govpn.PeerId]string)
- peersByIdLock sync.RWMutex
+ peersByID = make(map[govpn.PeerID]string)
+ peersByIDLock sync.RWMutex
knownPeers govpn.KnownPeers
kpLock sync.RWMutex
)
-func callUp(peerId *govpn.PeerId, remoteAddr string) (string, error) {
- ifaceName := confs[*peerId].Iface
- if confs[*peerId].Up != "" {
- result, err := govpn.ScriptCall(confs[*peerId].Up, ifaceName, remoteAddr)
+func callUp(peerID *govpn.PeerID, remoteAddr string) (string, error) {
+ ifaceName := confs[*peerID].Iface
+ if confs[*peerID].Up != "" {
+ result, err := govpn.ScriptCall(confs[*peerID].Up, ifaceName, remoteAddr)
if err != nil {
- govpn.Printf(`[script-failed bind="%s" path="%s" err="%s"]`, *bindAddr, confs[*peerId].Up, err)
+ govpn.Printf(
+ `[script-failed bind="%s" path="%s" err="%s"]`,
+ *bindAddr,
+ confs[*peerID].Up,
+ err,
+ )
return "", err
}
if ifaceName == "" {
}
}
if ifaceName == "" {
- govpn.Printf(`[tap-failed bind="%s" peer="%s"]`, *bindAddr, *peerId)
+ govpn.Printf(`[tap-failed bind="%s" peer="%s"]`, *bindAddr, *peerID)
}
return ifaceName, nil
}
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
"log"
"time"
- "github.com/go-yaml/yaml"
+ "gopkg.in/yaml.v2"
"cypherpunks.ru/govpn"
)
)
var (
- confs map[govpn.PeerId]*govpn.PeerConf
+ confs map[govpn.PeerID]*govpn.PeerConf
idsCache *govpn.MACCache
)
-func confRead() (*map[govpn.PeerId]*govpn.PeerConf, error) {
+func confRead() (*map[govpn.PeerID]*govpn.PeerConf, error) {
data, err := ioutil.ReadFile(*confPath)
if err != nil {
return nil, err
return nil, err
}
- confs := make(map[govpn.PeerId]*govpn.PeerConf, len(*confsRaw))
+ confs := make(map[govpn.PeerID]*govpn.PeerConf, len(*confsRaw))
for name, pc := range *confsRaw {
verifier, err := govpn.VerifierFromString(pc.VerifierRaw)
if err != nil {
}
conf := govpn.PeerConf{
Verifier: verifier,
- Id: verifier.Id,
+ ID: verifier.ID,
Name: name,
Iface: pc.Iface,
MTU: pc.MTU,
pc.TimeoutInt = govpn.TimeoutDefault
}
conf.Timeout = time.Second * time.Duration(pc.TimeoutInt)
- confs[*verifier.Id] = &conf
+ confs[*verifier.ID] = &conf
}
return &confs, nil
}
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
govpn.BothPrintf(`[terminating bind="%s"]`, *bindAddr)
for _, ps := range peers {
govpn.ScriptCall(
- confs[*ps.peer.Id].Down,
+ confs[*ps.peer.ID].Down,
ps.tap.Name,
ps.peer.Addr,
)
}
}
peersLock.Lock()
- peersByIdLock.Lock()
+ peersByIDLock.Lock()
kpLock.Lock()
for addr, ps := range peers {
ps.peer.BusyR.Lock()
govpn.Printf(`[peer-delete bind="%s" peer="%s"]`, *bindAddr, ps.peer)
delete(peers, addr)
delete(knownPeers, addr)
- delete(peersById, *ps.peer.Id)
+ delete(peersByID, *ps.peer.ID)
go govpn.ScriptCall(
- confs[*ps.peer.Id].Down,
+ confs[*ps.peer.ID].Down,
ps.tap.Name,
ps.peer.Addr,
)
}
hsLock.Unlock()
peersLock.Unlock()
- peersByIdLock.Unlock()
+ peersByIDLock.Unlock()
kpLock.Unlock()
}
}
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
break
}
prev += n
- peerId := idsCache.Find(buf[:prev])
- if peerId == nil {
+ peerID := idsCache.Find(buf[:prev])
+ if peerID == nil {
continue
}
if hs == nil {
- conf = confs[*peerId]
+ conf = confs[*peerID]
if conf == nil {
govpn.Printf(
`[conf-get-failed bind="%s" peer="%s"]`,
- *bindAddr, peerId.String(),
+ *bindAddr, peerID.String(),
)
break
}
hs.Zero()
govpn.Printf(
`[handshake-completed bind="%s" addr="%s" peer="%s"]`,
- *bindAddr, addr, peerId.String(),
+ *bindAddr, addr, peerID.String(),
)
- peersByIdLock.RLock()
- addrPrev, exists := peersById[*peer.Id]
- peersByIdLock.RUnlock()
+ peersByIDLock.RLock()
+ addrPrev, exists := peersByID[*peer.ID]
+ peersByIDLock.RUnlock()
if exists {
peersLock.Lock()
peers[addrPrev].terminator <- struct{}{}
terminator: make(chan struct{}),
}
go govpn.PeerTapProcessor(ps.peer, ps.tap, ps.terminator)
- peersByIdLock.Lock()
+ peersByIDLock.Lock()
kpLock.Lock()
delete(peers, addrPrev)
delete(knownPeers, addrPrev)
peers[addr] = ps
knownPeers[addr] = &peer
- peersById[*peer.Id] = addr
+ peersByID[*peer.ID] = addr
peersLock.Unlock()
- peersByIdLock.Unlock()
+ peersByIDLock.Unlock()
kpLock.Unlock()
govpn.Printf(
`[rehandshake-completed bind="%s" peer="%s"]`,
- *bindAddr, peerId.String(),
+ *bindAddr, peerID.String(),
)
} else {
- ifaceName, err := callUp(peer.Id, peer.Addr)
+ ifaceName, err := callUp(peer.ID, peer.Addr)
if err != nil {
peer = nil
break
if err != nil {
govpn.Printf(
`[tap-failed bind="%s" peer="%s" err="%s"]`,
- *bindAddr, peerId.String(), err,
+ *bindAddr, peerID.String(), err,
)
peer = nil
break
}
go govpn.PeerTapProcessor(ps.peer, ps.tap, ps.terminator)
peersLock.Lock()
- peersByIdLock.Lock()
+ peersByIDLock.Lock()
kpLock.Lock()
peers[addr] = ps
- peersById[*peer.Id] = addr
+ peersByID[*peer.ID] = addr
knownPeers[addr] = &peer
peersLock.Unlock()
- peersByIdLock.Unlock()
+ peersByIDLock.Unlock()
kpLock.Unlock()
- govpn.Printf(`[peer-created bind="%s" peer="%s"]`, *bindAddr, peerId.String())
+ govpn.Printf(`[peer-created bind="%s" peer="%s"]`, *bindAddr, peerID.String())
}
break
}
if !peer.PktProcess(buf[:i+govpn.NonceSize], tap, false) {
govpn.Printf(
`[packet-unauthenticated bind="%s" addr="%s" peer="%s"]`,
- *bindAddr, addr, peer.Id.String(),
+ *bindAddr, addr, peer.ID.String(),
)
break
}
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
var (
// Buffers for UDP parallel processing
- udpBufs chan []byte = make(chan []byte, 1<<8)
+ udpBufs = make(chan []byte, 1<<8)
)
func startUDP() {
var hs *govpn.Handshake
var addrPrev string
var exists bool
- var peerId *govpn.PeerId
- var peer *govpn.Peer
+ var peerID *govpn.PeerID
var conf *govpn.PeerConf
for {
buf = <-udpBufs
peersLock.RLock()
ps, exists = peers[addr]
peersLock.RUnlock()
- if !exists {
- goto CheckHandshake
+ if exists {
+ go func(peer *govpn.Peer, tap *govpn.TAP, buf []byte, n int) {
+ peer.PktProcess(buf[:n], tap, true)
+ udpBufs <- buf
+ }(ps.peer, ps.tap, buf, n)
+ continue
}
- go func(ps *govpn.Peer, tap *govpn.TAP, buf []byte, n int) {
- peer.PktProcess(buf[:n], tap, true)
- udpBufs <- buf
- }(ps.peer, ps.tap, buf, n)
- continue
- CheckHandshake:
+
hsLock.RLock()
hs, exists = handshakes[addr]
hsLock.RUnlock()
if !exists {
- goto CheckID
+ peerID = idsCache.Find(buf[:n])
+ if peerID == nil {
+ govpn.Printf(`[identity-unknown bind="%s" addr="%s"]`, *bindAddr, addr)
+ udpBufs <- buf
+ continue
+ }
+ conf = confs[*peerID]
+ if conf == nil {
+ govpn.Printf(
+ `[conf-get-failed bind="%s" peer="%s"]`,
+ *bindAddr, peerID.String(),
+ )
+ udpBufs <- buf
+ continue
+ }
+ hs := govpn.NewHandshake(
+ addr,
+ UDPSender{conn: conn, addr: raddr},
+ conf,
+ )
+ hs.Server(buf[:n])
+ udpBufs <- buf
+ hsLock.Lock()
+ handshakes[addr] = hs
+ hsLock.Unlock()
+ continue
}
- peer = hs.Server(buf[:n])
+
+ peer := hs.Server(buf[:n])
if peer == nil {
- goto Finished
+ udpBufs <- buf
+ continue
}
-
govpn.Printf(
`[handshake-completed bind="%s" addr="%s" peer="%s"]`,
- *bindAddr, addr, peerId.String(),
+ *bindAddr, addr, peerID.String(),
)
hs.Zero()
hsLock.Lock()
udpBufs <- make([]byte, govpn.MTUMax)
udpBufs <- make([]byte, govpn.MTUMax)
}()
- peersByIdLock.RLock()
- addrPrev, exists = peersById[*peer.Id]
- peersByIdLock.RUnlock()
+ peersByIDLock.RLock()
+ addrPrev, exists = peersByID[*peer.ID]
+ peersByIDLock.RUnlock()
if exists {
peersLock.Lock()
peers[addrPrev].terminator <- struct{}{}
- ps = &PeerState{
+ psNew := &PeerState{
peer: peer,
tap: peers[addrPrev].tap,
terminator: make(chan struct{}),
}
- go func(ps PeerState) {
- govpn.PeerTapProcessor(ps.peer, ps.tap, ps.terminator)
+ go func(peer *govpn.Peer, tap *govpn.TAP, terminator chan struct{}) {
+ govpn.PeerTapProcessor(peer, tap, terminator)
<-udpBufs
<-udpBufs
- }(*ps)
- peersByIdLock.Lock()
+ }(psNew.peer, psNew.tap, psNew.terminator)
+ peersByIDLock.Lock()
kpLock.Lock()
delete(peers, addrPrev)
delete(knownPeers, addrPrev)
- peers[addr] = ps
+ peers[addr] = psNew
knownPeers[addr] = &peer
- peersById[*peer.Id] = addr
+ peersByID[*peer.ID] = addr
peersLock.Unlock()
- peersByIdLock.Unlock()
+ peersByIDLock.Unlock()
kpLock.Unlock()
govpn.Printf(
`[rehandshake-completed bind="%s" peer="%s"]`,
- *bindAddr, peer.Id.String(),
+ *bindAddr, peer.ID.String(),
)
} else {
go func(addr string, peer *govpn.Peer) {
- ifaceName, err := callUp(peer.Id, peer.Addr)
+ ifaceName, err := callUp(peer.ID, peer.Addr)
if err != nil {
return
}
if err != nil {
govpn.Printf(
`[tap-failed bind="%s" peer="%s" err="%s"]`,
- *bindAddr, peer.Id.String(), err,
+ *bindAddr, peer.ID.String(), err,
)
return
}
- ps = &PeerState{
+ psNew := &PeerState{
peer: peer,
tap: tap,
terminator: make(chan struct{}),
}
- go func(ps PeerState) {
- govpn.PeerTapProcessor(ps.peer, ps.tap, ps.terminator)
+ go func(peer *govpn.Peer, tap *govpn.TAP, terminator chan struct{}) {
+ govpn.PeerTapProcessor(peer, tap, terminator)
<-udpBufs
<-udpBufs
- }(*ps)
+ }(psNew.peer, psNew.tap, psNew.terminator)
peersLock.Lock()
- peersByIdLock.Lock()
+ peersByIDLock.Lock()
kpLock.Lock()
- peers[addr] = ps
+ peers[addr] = psNew
knownPeers[addr] = &peer
- peersById[*peer.Id] = addr
+ peersByID[*peer.ID] = addr
peersLock.Unlock()
- peersByIdLock.Unlock()
+ peersByIDLock.Unlock()
kpLock.Unlock()
- govpn.Printf(`[peer-created bind="%s" peer="%s"]`, *bindAddr, peer.Id.String())
+ govpn.Printf(`[peer-created bind="%s" peer="%s"]`, *bindAddr, peer.ID.String())
}(addr, peer)
}
- goto Finished
- CheckID:
- peerId = idsCache.Find(buf[:n])
- if peerId == nil {
- govpn.Printf(`[identity-unknown bind="%s" addr="%s"]`, *bindAddr, addr)
- goto Finished
- }
- conf = confs[*peerId]
- if conf == nil {
- govpn.Printf(
- `[conf-get-failed bind="%s" peer="%s"]`,
- *bindAddr, peerId.String(),
- )
- goto Finished
- }
- hs = govpn.NewHandshake(
- addr,
- UDPSender{conn: conn, addr: raddr},
- conf,
- )
- hs.Server(buf[:n])
- hsLock.Lock()
- handshakes[addr] = hs
- hsLock.Unlock()
- Finished:
udpBufs <- buf
}
}()
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
if _, err = io.ReadFull(govpn.Rand, id[:]); err != nil {
log.Fatalln(err)
}
- pid := govpn.PeerId(*id)
+ pid := govpn.PeerID(*id)
v := govpn.VerifierNew(*sOpt, *tOpt, *pOpt, &pid)
v.PasswordApply(key)
fmt.Println(v.LongForm())
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
)
var (
- testKey *[32]byte = new([32]byte)
+ testKey = new([32]byte)
)
func init() {
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
)
type PeerConf struct {
- Id *PeerId `yaml:"-"`
+ ID *PeerID `yaml:"-"`
Name string `yaml:"name"`
Iface string `yaml:"iface"`
MTU int `yaml:"mtu"`
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
)
var (
- Rand io.Reader = rand.Reader
+ Rand = rand.Reader
)
type EGDRand string
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
)
var (
- testKey *[32]byte = new([32]byte)
+ testKey = new([32]byte)
)
func init() {
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
}
// Generate ID tag from client identification and data.
-func idTag(id *PeerId, timeSync int, data []byte) []byte {
+func idTag(id *PeerID, timeSync int, data []byte) []byte {
enc := make([]byte, 8)
copy(enc, data)
AddTimeSync(timeSync, enc)
panic(err)
}
mac.Write(enc)
- mac.Sum(enc[:0])
- return enc
+ sum := mac.Sum(nil)
+ return sum[len(sum)-8:]
}
// Start handshake's procedure from the client. It is the entry point
-// for starting the handshake procedure. // First handshake packet
-// will be sent immediately.
+// for starting the handshake procedure.
+// First handshake packet will be sent immediately.
func HandshakeStart(addr string, conn io.Writer, conf *PeerConf) *Handshake {
state := NewHandshake(addr, conn, conf)
var dhPubRepr *[32]byte
chacha20.XORKeyStream(enc, enc, state.rNonce, state.dsaPubH)
}
data := append(state.rNonce[8:], enc...)
- data = append(data, idTag(state.Conf.Id, state.Conf.TimeSync, state.rNonce[8:])...)
+ data = append(data, idTag(state.Conf.ID, state.Conf.TimeSync, state.rNonce[8:])...)
state.conn.Write(data)
return state
}
// Send that to client
h.conn.Write(append(encPub, append(
- encRs, idTag(h.Conf.Id, h.Conf.TimeSync, encPub)...,
+ encRs, idTag(h.Conf.ID, h.Conf.TimeSync, encPub)...,
)...))
h.LastPing = time.Now()
} else
} else {
chacha20.XORKeyStream(enc, enc, h.rNonceNext(2), h.key)
}
- h.conn.Write(append(enc, idTag(h.Conf.Id, h.Conf.TimeSync, enc)...))
+ h.conn.Write(append(enc, idTag(h.Conf.ID, h.Conf.TimeSync, enc)...))
// Switch peer
peer := newPeer(
}
// Send that to server
- h.conn.Write(append(enc, idTag(h.Conf.Id, h.Conf.TimeSync, enc)...))
+ h.conn.Write(append(enc, idTag(h.Conf.ID, h.Conf.TimeSync, enc)...))
h.LastPing = time.Now()
} else
// ENC(K, R+2, RC) + IDtag
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
func TestHandshakeSymmetric(t *testing.T) {
// initial values are taken from peer_test.go's init()
- v := VerifierNew(1<<10, 1<<4, 1, &testPeerId)
+ v := VerifierNew(1<<10, 1<<4, 1, &testPeerID)
testConf.Verifier = v
testConf.DSAPriv = v.PasswordApply("does not matter")
hsS := NewHandshake("server", Dummy{&testCt}, testConf)
func TestHandshakeNoiseSymmetric(t *testing.T) {
// initial values are taken from peer_test.go's init()
- v := VerifierNew(1<<10, 1<<4, 1, &testPeerId)
+ v := VerifierNew(1<<10, 1<<4, 1, &testPeerID)
testConf.Verifier = v
testConf.DSAPriv = v.PasswordApply("does not matter")
testConf.Noise = true
}
func TestHandshakeEnclessSymmetric(t *testing.T) {
// initial values are taken from peer_test.go's init()
- v := VerifierNew(1<<10, 1<<4, 1, &testPeerId)
+ v := VerifierNew(1<<10, 1<<4, 1, &testPeerID)
testConf.Verifier = v
testConf.DSAPriv = v.PasswordApply("does not matter")
testConf.Encless = true
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
IDSize = 128 / 8
)
-type PeerId [IDSize]byte
+type PeerID [IDSize]byte
-func (id PeerId) String() string {
+func (id PeerID) String() string {
return base64.RawStdEncoding.EncodeToString(id[:])
}
-func (id PeerId) MarshalJSON() ([]byte, error) {
+func (id PeerID) MarshalJSON() ([]byte, error) {
return []byte(`"` + id.String() + `"`), nil
}
}
type MACCache struct {
- cache map[PeerId]*MACAndTimeSync
+ cache map[PeerID]*MACAndTimeSync
l sync.RWMutex
}
func NewMACCache() *MACCache {
- return &MACCache{cache: make(map[PeerId]*MACAndTimeSync)}
+ return &MACCache{cache: make(map[PeerID]*MACAndTimeSync)}
}
// Remove disappeared keys, add missing ones with initialized MACs.
-func (mc *MACCache) Update(peers *map[PeerId]*PeerConf) {
+func (mc *MACCache) Update(peers *map[PeerID]*PeerConf) {
mc.l.Lock()
- for pid, _ := range mc.cache {
+ for pid := range mc.cache {
if _, exists := (*peers)[pid]; !exists {
log.Println("Cleaning key:", pid)
delete(mc.cache, pid)
// Try to find peer's identity (that equals to MAC)
// by taking first blocksize sized bytes from data at the beginning
// as plaintext and last bytes as cyphertext.
-func (mc *MACCache) Find(data []byte) *PeerId {
+func (mc *MACCache) Find(data []byte) *PeerID {
if len(data) < 8*2 {
return nil
}
buf := make([]byte, 8)
+ sum := make([]byte, 32)
mc.l.RLock()
for pid, mt := range mc.cache {
copy(buf, data)
mt.l.Lock()
mt.mac.Reset()
mt.mac.Write(buf)
- mt.mac.Sum(buf[:0])
+ mt.mac.Sum(sum[:0])
mt.l.Unlock()
- if subtle.ConstantTimeCompare(buf, data[len(data)-8:]) == 1 {
- ppid := PeerId(pid)
+ if subtle.ConstantTimeCompare(sum[len(sum)-8:], data[len(data)-8:]) == 1 {
+ ppid := PeerID(pid)
mc.l.RUnlock()
return &ppid
}
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
if err != nil {
panic(err)
}
+ sum := make([]byte, mac.Size())
nonces := make(chan *[NonceSize]byte, NonceBucketSize*3)
go func() {
for {
buf := new([NonceSize]byte)
binary.BigEndian.PutUint64(buf[:], i)
mac.Write(buf[:])
- mac.Sum(buf[:0])
+ mac.Sum(sum[0:])
+ copy(buf[:], sum)
nonces <- buf
mac.Reset()
i += 2
// Basic
Addr string
- Id *PeerId
+ ID *PeerID
Conn io.Writer `json:"-"`
// Traffic behaviour
Encless bool
MTU int
- key *[SSize]byte `json:"-"`
+ key *[SSize]byte
// Timers
Timeout time.Duration `json:"-"`
}
func (p *Peer) String() string {
- return p.Id.String() + ":" + p.Addr
+ return p.ID.String() + ":" + p.Addr
}
// Zero peer's memory state.
peer := Peer{
Addr: addr,
- Id: conf.Id,
+ ID: conf.ID,
Conn: conn,
NoiseEnable: noiseEnable,
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
testPeer *Peer
testPt []byte
testCt []byte
- testPeerId PeerId
+ testPeerID PeerID
testConf *PeerConf
)
func init() {
id := new([IDSize]byte)
- testPeerId = PeerId(*id)
+ testPeerID = PeerID(*id)
testConf = &PeerConf{
- Id: &testPeerId,
+ ID: &testPeerID,
MTU: MTUDefault,
Timeout: time.Second * time.Duration(TimeoutDefault),
}
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
*/
package govpn
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
*/
package govpn
/*
GoVPN -- simple secure free software virtual private network daemon
-Copyright (C) 2014-2016 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
S int
T int
P int
- Id *PeerId
+ ID *PeerID
Pub *[ed25519.PublicKeySize]byte
}
// Generate new verifier for given peer, with specified password and
// hashing parameters.
-func VerifierNew(s, t, p int, id *PeerId) *Verifier {
- return &Verifier{S: s, T: t, P: p, Id: id}
+func VerifierNew(s, t, p int, id *PeerID) *Verifier {
+ return &Verifier{S: s, T: t, P: p, ID: id}
}
func blake2bKeyless() hash.Hash {
// Apply the password: create Ed25519 keypair based on it, save public
// key in verifier.
func (v *Verifier) PasswordApply(password string) *[ed25519.PrivateKeySize]byte {
- r := balloon.H(blake2bKeyless, []byte(password), v.Id[:], v.S, v.T, v.P)
+ r := balloon.H(blake2bKeyless, []byte(password), v.ID[:], v.S, v.T, v.P)
defer SliceZero(r)
src := bytes.NewBuffer(r)
pub, prv, err := ed25519.GenerateKey(src)
v := Verifier{S: s, T: t, P: p}
id := new([IDSize]byte)
copy(id[:], salt)
- pid := PeerId(*id)
- v.Id = &pid
+ pid := PeerID(*id)
+ v.ID = &pid
if len(ss) == 5 {
pub, err := base64.RawStdEncoding.DecodeString(ss[4])
if err != nil {
func (v *Verifier) ShortForm() string {
return fmt.Sprintf(
"$balloon$s=%d,t=%d,p=%d$%s",
- v.S, v.T, v.P, base64.RawStdEncoding.EncodeToString(v.Id[:]),
+ v.S, v.T, v.P, base64.RawStdEncoding.EncodeToString(v.ID[:]),
)
}
-Subproject commit 278e1ec8e8a6e017cd07577924d6766039146ced
+Subproject commit 5312a61534124124185d41f09206b9fef1d88403
+++ /dev/null
-Subproject commit e4d366fc3c7938e2958e662b4258c7a89e1f0e3e
-Subproject commit b2fa06b6af4b7c9bfeb8569ab7b17f04550717bf
+Subproject commit 41d678d1df78cd0410143162dff954e6dc09300f
--- /dev/null
+Subproject commit a5b47d31c556af34a302ce5d659e6fea44d90de0
src/cypherpunks.ru/balloon
src/github.com/agl/ed25519
src/github.com/bigeagle/water
- src/github.com/go-yaml/yaml
+ src/gopkg.in/yaml.v2
src/golang.org/x/crypto
"
for repo in $repos; do
@url{http://www.govpn.info/}.
EOF
make -C doc
-rm -r doc/.well-known doc/govpn.html/.well-known
+./utils/news.sh
+rm -r doc/.well-known doc/govpn.html/.well-known utils/news.sh
rm utils/makedist.sh
find . -name .git -type d | xargs rm -fr
find . -name .gitignore -delete
+rm .gitmodules
cd ..
tar cvf govpn-"$release".tar govpn-"$release"
Идентификатор GPG ключа: 0xF2F59045FFE2F4A1 GoVPN releases <releases@govpn.info>
Отпечаток: D269 9B73 3C41 2068 D8DA 656E F2F5 9045 FFE2 F4A1
-Пожалуйста все вопросы касающиеся использования GoVPN, отчёты об ошибках
+Пожалуйста, все вопросы касающиеся использования GoVPN, отчёты об ошибках
и патчи отправляйте в govpn-devel почтовую рассылку:
https://lists.cypherpunks.ru/pipermail/govpn-devel/
EOF
--- /dev/null
+#!/bin/sh -ex
+
+texi=`mktemp`
+
+cat > $texi <<EOF
+\input texinfo
+@documentencoding UTF-8
+@settitle NEWS
+
+@node News
+@unnumbered News
+
+`sed -n '5,$p' < doc/news.texi`
+
+@bye
+EOF
+makeinfo --plaintext -o NEWS $texi
+
+cat > $texi <<EOF
+\input texinfo
+@documentencoding UTF-8
+@settitle NEWS.RU
+
+@node Новости
+@unnumbered Новости
+
+`sed -n '3,$p' < doc/news.ru.texi | sed 's/^@subsection/@section/'`
+
+@bye
+EOF
+makeinfo --plaintext -o NEWS.RU $texi
+
+rm -f $texi