From: Sergey Matveev Date: Tue, 24 Jan 2017 19:34:26 +0000 (+0300) Subject: Merge branch 'develop' X-Git-Tag: 7.1^0 X-Git-Url: http://www.git.cypherpunks.ru/?p=govpn.git;a=commitdiff_plain;h=eb63bd7cb200da72cc782f4fef873ebfdc6c0eba;hp=035ce75027dd6b55905c8719c0af3e09f80debc3 Merge branch 'develop' --- diff --git a/.gitmodules b/.gitmodules index 82df1f7..c837a03 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,9 +7,10 @@ [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 diff --git a/NEWS b/NEWS deleted file mode 120000 index 8be52e4..0000000 --- a/NEWS +++ /dev/null @@ -1 +0,0 @@ -doc/news.texi \ No newline at end of file diff --git a/NEWS.RU b/NEWS.RU deleted file mode 120000 index 85f9daf..0000000 --- a/NEWS.RU +++ /dev/null @@ -1 +0,0 @@ -doc/news.ru.texi \ No newline at end of file diff --git a/THANKS b/THANKS index 38cc203..a7fe0af 100644 --- a/THANKS +++ b/THANKS @@ -1,7 +1,5 @@ -* 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 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 for AUR port maintaining and his documentation related fixes. +* Watson Ladd for suggestion of Elligator encoding. +* Zhuoyun Wei for AUR port maintaining and + his documentation related fixes. +* Bruno Clermont for finding serious bugs + and code refactoring diff --git a/VERSION b/VERSION index 4fedf1d..0f0fefa 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.0 +7.1 diff --git a/doc/download.texi b/doc/download.texi index 31977c6..60ac685 100644 --- a/doc/download.texi +++ b/doc/download.texi @@ -5,9 +5,23 @@ You can obtain releases source code prepared tarballs from the links below (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} diff --git a/doc/index.texi b/doc/index.texi index b962eac..624abba 100644 --- a/doc/index.texi +++ b/doc/index.texi @@ -7,7 +7,7 @@ This manual is for GoVPN -- simple free software virtual private network 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 diff --git a/doc/installation.texi b/doc/installation.texi index 1443d7f..9abc822 100644 --- a/doc/installation.texi +++ b/doc/installation.texi @@ -18,17 +18,7 @@ and GNU ones are fine) is recommended for convenient building. @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}. @@ -43,8 +33,8 @@ binaries will be built in the current directory: % 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. diff --git a/doc/integrity.texi b/doc/integrity.texi index b9bc1a1..5fda02f 100644 --- a/doc/integrity.texi +++ b/doc/integrity.texi @@ -1,7 +1,7 @@ @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 diff --git a/doc/news.ru.texi b/doc/news.ru.texi index 81c3139..9f7ebf0 100644 --- a/doc/news.ru.texi +++ b/doc/news.ru.texi @@ -1,6 +1,15 @@ @node Новости @section Новости +@node Релиз 7.1 +@subsection Релиз 7.1 +@itemize +@item Исправлена ошибка в коде генерирования и определения идентификации +клиента: параллельно работающие клиенты могут быть неправильно +определены, не давая возможности их подсоединения и позволяя DPI +выявлять GoVPN пакеты. +@end itemize + @node Релиз 7.0 @subsection Релиз 7.0 @itemize @@ -75,8 +84,8 @@ up- и down- скрипты через переменные окружения. @node Релиз 5.4 @subsection Релиз 5.4 @itemize -@item Добавлена возможность требования @ref{Timesync, синхронизации -времени}. Она добавит временные метки в PRP аутентификацию сообщений +@item Добавлена возможность требования синхронизации +времени. Она добавит временные метки в PRP аутентификацию сообщений рукопожатия, не позволяя повторить ранее перехваченные пакеты и получить ответ от сервера, делая его видимым для DPI. @end itemize @@ -111,15 +120,15 @@ stderr. @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 @@ -152,9 +161,9 @@ stderr. @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. @@ -165,7 +174,7 @@ stderr. @node Релиз 3.4 @subsection Релиз 3.4 @itemize -@item Возможность использовать внешний @ref{EGD} совместимый PRNG. +@item Возможность использовать внешний EGD совместимый PRNG. Теперь вы можете использовать GoVPN даже на системах с плохим @file{/dev/random}. @item Опция @option{-noncediff} удалена. Она заменена на хранилище уже @@ -303,9 +312,3 @@ A-EKE с PBKDF2 верификаторами устойчивы к атакам @itemize @item Поддержка FreeBSD. @end itemize - -@node Релиз 1.0 -@subsection Релиз 1.0 -@itemize -@item Первый стабильный релиз. -@end itemize diff --git a/doc/news.texi b/doc/news.texi index 5a6db8f..21104e0 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -3,6 +3,14 @@ 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 @@ -74,7 +82,7 @@ has some specific issues that caused panics on previous versions. @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. @@ -107,15 +115,15 @@ with @emph{BLAKE2b} in handshake code. @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 @@ -147,9 +155,9 @@ hidden. Now they are indistinguishable from transport messages. @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 @@ -159,7 +167,7 @@ reasons. @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 @@ -298,9 +306,3 @@ consuming and resource heavy computations. @itemize @item FreeBSD support. @end itemize - -@node Release 1.0 -@section Release 1.0 -@itemize -@item Initial stable release. -@end itemize diff --git a/doc/sources.texi b/doc/sources.texi index e7a1375..f3864ef 100644 --- a/doc/sources.texi +++ b/doc/sources.texi @@ -3,8 +3,8 @@ 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} diff --git a/doc/thanks.texi b/doc/thanks.texi index 0a6757c..b0426dd 100644 --- a/doc/thanks.texi +++ b/doc/thanks.texi @@ -4,12 +4,8 @@ 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 diff --git a/src/cypherpunks.ru/govpn/aont/aont_test.go b/src/cypherpunks.ru/govpn/aont/aont_test.go index 0ef140c..b586775 100644 --- a/src/cypherpunks.ru/govpn/aont/aont_test.go +++ b/src/cypherpunks.ru/govpn/aont/aont_test.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -27,7 +27,7 @@ import ( ) var ( - testKey *[16]byte = new([16]byte) + testKey = new([16]byte) ) func init() { diff --git a/src/cypherpunks.ru/govpn/aont/oaep.go b/src/cypherpunks.ru/govpn/aont/oaep.go index 4b780ba..b648ccb 100644 --- a/src/cypherpunks.ru/govpn/aont/oaep.go +++ b/src/cypherpunks.ru/govpn/aont/oaep.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -48,7 +48,7 @@ const ( ) var ( - dummyNonce *[16]byte = new([16]byte) + dummyNonce = new([16]byte) ) // Encode the data, produce AONT package. Data size will be larger than diff --git a/src/cypherpunks.ru/govpn/client/client.go b/src/cypherpunks.ru/govpn/client/client.go new file mode 100644 index 0000000..8102cc6 --- /dev/null +++ b/src/cypherpunks.ru/govpn/client/client.go @@ -0,0 +1,160 @@ +/* +GoVPN -- simple secure free software virtual private network daemon +Copyright (C) 2014-2017 Sergey Matveev + +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 . +*/ + +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 +} diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-client/proxy.go b/src/cypherpunks.ru/govpn/client/proxy.go similarity index 61% rename from src/cypherpunks.ru/govpn/cmd/govpn-client/proxy.go rename to src/cypherpunks.ru/govpn/client/proxy.go index 0a6729c..be7d114 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-client/proxy.go +++ b/src/cypherpunks.ru/govpn/client/proxy.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -16,32 +16,34 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -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)) @@ -50,8 +52,9 @@ func proxyTCP(timeouted, rehandshaking, termination chan struct{}) { &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) } diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-client/tcp.go b/src/cypherpunks.ru/govpn/client/tcp.go similarity index 50% rename from src/cypherpunks.ru/govpn/cmd/govpn-client/tcp.go rename to src/cypherpunks.ru/govpn/client/tcp.go index 57a412d..40d81ca 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-client/tcp.go +++ b/src/cypherpunks.ru/govpn/client/tcp.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -16,11 +16,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -package main +package client import ( "bytes" - "log" + "fmt" "net" "sync/atomic" "time" @@ -28,22 +28,24 @@ import ( "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 @@ -52,27 +54,30 @@ func handleTCP(conn *net.TCPConn, timeouted, rehandshaking, termination chan str 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]) @@ -80,15 +85,15 @@ HandshakeCycle: 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 { @@ -103,20 +108,23 @@ HandshakeCycle: 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 @@ -128,14 +136,14 @@ TransportCycle: 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]) @@ -146,5 +154,7 @@ TransportCycle: terminator <- struct{}{} } peer.Zero() - conn.Close() + if err = conn.Close(); err != nil { + c.Error <- err + } } diff --git a/src/cypherpunks.ru/govpn/client/udp.go b/src/cypherpunks.ru/govpn/client/udp.go new file mode 100644 index 0000000..bb7045a --- /dev/null +++ b/src/cypherpunks.ru/govpn/client/udp.go @@ -0,0 +1,114 @@ +/* +GoVPN -- simple secure free software virtual private network daemon +Copyright (C) 2014-2017 Sergey Matveev + +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 . +*/ + +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 + } +} diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-client/main.go b/src/cypherpunks.ru/govpn/cmd/govpn-client/main.go index 36ff72a..8fcd988 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-client/main.go +++ b/src/cypherpunks.ru/govpn/cmd/govpn-client/main.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -23,46 +23,41 @@ import ( "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) @@ -72,72 +67,74 @@ func main() { 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() @@ -145,38 +142,9 @@ func main() { 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) } diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-client/udp.go b/src/cypherpunks.ru/govpn/cmd/govpn-client/udp.go deleted file mode 100644 index 96dbfba..0000000 --- a/src/cypherpunks.ru/govpn/cmd/govpn-client/udp.go +++ /dev/null @@ -1,106 +0,0 @@ -/* -GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev - -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 . -*/ - -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() -} diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-server/common.go b/src/cypherpunks.ru/govpn/cmd/govpn-server/common.go index 7c2dd41..f18d34b 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-server/common.go +++ b/src/cypherpunks.ru/govpn/cmd/govpn-server/common.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -35,22 +35,27 @@ var ( 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 == "" { @@ -62,7 +67,7 @@ func callUp(peerId *govpn.PeerId, remoteAddr string) (string, error) { } } 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 } diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-server/conf.go b/src/cypherpunks.ru/govpn/cmd/govpn-server/conf.go index ea61c81..62eca02 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-server/conf.go +++ b/src/cypherpunks.ru/govpn/cmd/govpn-server/conf.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -24,7 +24,7 @@ import ( "log" "time" - "github.com/go-yaml/yaml" + "gopkg.in/yaml.v2" "cypherpunks.ru/govpn" ) @@ -34,11 +34,11 @@ const ( ) 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 @@ -49,7 +49,7 @@ func confRead() (*map[govpn.PeerId]*govpn.PeerConf, error) { 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 { @@ -67,7 +67,7 @@ func confRead() (*map[govpn.PeerId]*govpn.PeerConf, error) { } conf := govpn.PeerConf{ Verifier: verifier, - Id: verifier.Id, + ID: verifier.ID, Name: name, Iface: pc.Iface, MTU: pc.MTU, @@ -82,7 +82,7 @@ func confRead() (*map[govpn.PeerId]*govpn.PeerConf, error) { pc.TimeoutInt = govpn.TimeoutDefault } conf.Timeout = time.Second * time.Duration(pc.TimeoutInt) - confs[*verifier.Id] = &conf + confs[*verifier.ID] = &conf } return &confs, nil } diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-server/main.go b/src/cypherpunks.ru/govpn/cmd/govpn-server/main.go index 68a0172..2beb396 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-server/main.go +++ b/src/cypherpunks.ru/govpn/cmd/govpn-server/main.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -108,7 +108,7 @@ MainCycle: 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, ) @@ -125,7 +125,7 @@ MainCycle: } } peersLock.Lock() - peersByIdLock.Lock() + peersByIDLock.Lock() kpLock.Lock() for addr, ps := range peers { ps.peer.BusyR.Lock() @@ -135,9 +135,9 @@ MainCycle: 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, ) @@ -146,7 +146,7 @@ MainCycle: } hsLock.Unlock() peersLock.Unlock() - peersByIdLock.Unlock() + peersByIDLock.Unlock() kpLock.Unlock() } } diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-server/proxy.go b/src/cypherpunks.ru/govpn/cmd/govpn-server/proxy.go index 02c1f0f..87e3455 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-server/proxy.go +++ b/src/cypherpunks.ru/govpn/cmd/govpn-server/proxy.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-server/tcp.go b/src/cypherpunks.ru/govpn/cmd/govpn-server/tcp.go index bfb4709..c36da3f 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-server/tcp.go +++ b/src/cypherpunks.ru/govpn/cmd/govpn-server/tcp.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -71,16 +71,16 @@ func handleTCP(conn net.Conn) { 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 } @@ -94,11 +94,11 @@ func handleTCP(conn net.Conn) { 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{}{} @@ -109,22 +109,22 @@ func handleTCP(conn net.Conn) { 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 @@ -133,7 +133,7 @@ func handleTCP(conn net.Conn) { if err != nil { govpn.Printf( `[tap-failed bind="%s" peer="%s" err="%s"]`, - *bindAddr, peerId.String(), err, + *bindAddr, peerID.String(), err, ) peer = nil break @@ -145,15 +145,15 @@ func handleTCP(conn net.Conn) { } 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 } @@ -188,7 +188,7 @@ func handleTCP(conn net.Conn) { 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 } diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-server/udp.go b/src/cypherpunks.ru/govpn/cmd/govpn-server/udp.go index 98993d3..cdcfb56 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-server/udp.go +++ b/src/cypherpunks.ru/govpn/cmd/govpn-server/udp.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -36,7 +36,7 @@ func (c UDPSender) Write(data []byte) (int, error) { var ( // Buffers for UDP parallel processing - udpBufs chan []byte = make(chan []byte, 1<<8) + udpBufs = make(chan []byte, 1<<8) ) func startUDP() { @@ -61,8 +61,7 @@ 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 @@ -76,29 +75,54 @@ func startUDP() { 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() @@ -109,39 +133,39 @@ func startUDP() { 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 } @@ -149,57 +173,32 @@ func startUDP() { 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 } }() diff --git a/src/cypherpunks.ru/govpn/cmd/govpn-verifier/main.go b/src/cypherpunks.ru/govpn/cmd/govpn-verifier/main.go index a83f9d1..aac36ba 100644 --- a/src/cypherpunks.ru/govpn/cmd/govpn-verifier/main.go +++ b/src/cypherpunks.ru/govpn/cmd/govpn-verifier/main.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -62,7 +62,7 @@ func main() { 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()) diff --git a/src/cypherpunks.ru/govpn/cnw/cnw.go b/src/cypherpunks.ru/govpn/cnw/cnw.go index c5d41a6..eaf0958 100644 --- a/src/cypherpunks.ru/govpn/cnw/cnw.go +++ b/src/cypherpunks.ru/govpn/cnw/cnw.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 diff --git a/src/cypherpunks.ru/govpn/cnw/cnw_test.go b/src/cypherpunks.ru/govpn/cnw/cnw_test.go index cbb28e9..29e408f 100644 --- a/src/cypherpunks.ru/govpn/cnw/cnw_test.go +++ b/src/cypherpunks.ru/govpn/cnw/cnw_test.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -28,7 +28,7 @@ import ( ) var ( - testKey *[32]byte = new([32]byte) + testKey = new([32]byte) ) func init() { diff --git a/src/cypherpunks.ru/govpn/common.go b/src/cypherpunks.ru/govpn/common.go index 98137c1..030794c 100644 --- a/src/cypherpunks.ru/govpn/common.go +++ b/src/cypherpunks.ru/govpn/common.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 diff --git a/src/cypherpunks.ru/govpn/conf.go b/src/cypherpunks.ru/govpn/conf.go index c8232d6..7a9c4b8 100644 --- a/src/cypherpunks.ru/govpn/conf.go +++ b/src/cypherpunks.ru/govpn/conf.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -25,7 +25,7 @@ import ( ) type PeerConf struct { - Id *PeerId `yaml:"-"` + ID *PeerID `yaml:"-"` Name string `yaml:"name"` Iface string `yaml:"iface"` MTU int `yaml:"mtu"` diff --git a/src/cypherpunks.ru/govpn/egd.go b/src/cypherpunks.ru/govpn/egd.go index 3d0b791..f54c116 100644 --- a/src/cypherpunks.ru/govpn/egd.go +++ b/src/cypherpunks.ru/govpn/egd.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -25,7 +25,7 @@ import ( ) var ( - Rand io.Reader = rand.Reader + Rand = rand.Reader ) type EGDRand string diff --git a/src/cypherpunks.ru/govpn/encless.go b/src/cypherpunks.ru/govpn/encless.go index bd42f1d..966a2dd 100644 --- a/src/cypherpunks.ru/govpn/encless.go +++ b/src/cypherpunks.ru/govpn/encless.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 diff --git a/src/cypherpunks.ru/govpn/encless_test.go b/src/cypherpunks.ru/govpn/encless_test.go index fc00d27..e0c78c4 100644 --- a/src/cypherpunks.ru/govpn/encless_test.go +++ b/src/cypherpunks.ru/govpn/encless_test.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -27,7 +27,7 @@ import ( ) var ( - testKey *[32]byte = new([32]byte) + testKey = new([32]byte) ) func init() { diff --git a/src/cypherpunks.ru/govpn/handshake.go b/src/cypherpunks.ru/govpn/handshake.go index a3ef2b5..a824ace 100644 --- a/src/cypherpunks.ru/govpn/handshake.go +++ b/src/cypherpunks.ru/govpn/handshake.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -132,7 +132,7 @@ func NewHandshake(addr string, conn io.Writer, conf *PeerConf) *Handshake { } // 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) @@ -141,13 +141,13 @@ func idTag(id *PeerId, timeSync int, data []byte) []byte { 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 @@ -174,7 +174,7 @@ func HandshakeStart(addr string, conn io.Writer, conf *PeerConf) *Handshake { 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 } @@ -260,7 +260,7 @@ func (h *Handshake) Server(data []byte) *Peer { // 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 @@ -316,7 +316,7 @@ func (h *Handshake) Server(data []byte) *Peer { } 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( @@ -416,7 +416,7 @@ func (h *Handshake) Client(data []byte) *Peer { } // 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 diff --git a/src/cypherpunks.ru/govpn/handshake_test.go b/src/cypherpunks.ru/govpn/handshake_test.go index bbe9841..0771465 100644 --- a/src/cypherpunks.ru/govpn/handshake_test.go +++ b/src/cypherpunks.ru/govpn/handshake_test.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -24,7 +24,7 @@ import ( 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) @@ -41,7 +41,7 @@ func TestHandshakeSymmetric(t *testing.T) { 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 @@ -59,7 +59,7 @@ func TestHandshakeNoiseSymmetric(t *testing.T) { } 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 diff --git a/src/cypherpunks.ru/govpn/identity.go b/src/cypherpunks.ru/govpn/identity.go index ece2dfc..262bca6 100644 --- a/src/cypherpunks.ru/govpn/identity.go +++ b/src/cypherpunks.ru/govpn/identity.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -34,13 +34,13 @@ const ( 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 } @@ -51,18 +51,18 @@ type MACAndTimeSync struct { } 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) @@ -101,11 +101,12 @@ func AddTimeSync(ts int, data []byte) { // 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) @@ -113,10 +114,10 @@ func (mc *MACCache) Find(data []byte) *PeerId { 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 } diff --git a/src/cypherpunks.ru/govpn/logger.go b/src/cypherpunks.ru/govpn/logger.go index b110ce3..48a3235 100644 --- a/src/cypherpunks.ru/govpn/logger.go +++ b/src/cypherpunks.ru/govpn/logger.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 diff --git a/src/cypherpunks.ru/govpn/peer.go b/src/cypherpunks.ru/govpn/peer.go index 22c893c..e43dc9c 100644 --- a/src/cypherpunks.ru/govpn/peer.go +++ b/src/cypherpunks.ru/govpn/peer.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -56,13 +56,15 @@ func newNonces(key *[32]byte, i uint64) chan *[NonceSize]byte { 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 @@ -86,7 +88,7 @@ type Peer struct { // Basic Addr string - Id *PeerId + ID *PeerID Conn io.Writer `json:"-"` // Traffic behaviour @@ -96,7 +98,7 @@ type Peer struct { Encless bool MTU int - key *[SSize]byte `json:"-"` + key *[SSize]byte // Timers Timeout time.Duration `json:"-"` @@ -133,7 +135,7 @@ type Peer struct { } func (p *Peer) String() string { - return p.Id.String() + ":" + p.Addr + return p.ID.String() + ":" + p.Addr } // Zero peer's memory state. @@ -183,7 +185,7 @@ func newPeer(isClient bool, addr string, conn io.Writer, conf *PeerConf, key *[S peer := Peer{ Addr: addr, - Id: conf.Id, + ID: conf.ID, Conn: conn, NoiseEnable: noiseEnable, diff --git a/src/cypherpunks.ru/govpn/peer_test.go b/src/cypherpunks.ru/govpn/peer_test.go index 18bd5fe..6c16469 100644 --- a/src/cypherpunks.ru/govpn/peer_test.go +++ b/src/cypherpunks.ru/govpn/peer_test.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -28,7 +28,7 @@ var ( testPeer *Peer testPt []byte testCt []byte - testPeerId PeerId + testPeerID PeerID testConf *PeerConf ) @@ -45,9 +45,9 @@ func (d Dummy) Write(b []byte) (int, error) { 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), } diff --git a/src/cypherpunks.ru/govpn/stats.go b/src/cypherpunks.ru/govpn/stats.go index 1d95674..c8ea622 100644 --- a/src/cypherpunks.ru/govpn/stats.go +++ b/src/cypherpunks.ru/govpn/stats.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 diff --git a/src/cypherpunks.ru/govpn/tap.go b/src/cypherpunks.ru/govpn/tap.go index 9010c55..faf88ba 100644 --- a/src/cypherpunks.ru/govpn/tap.go +++ b/src/cypherpunks.ru/govpn/tap.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 diff --git a/src/cypherpunks.ru/govpn/tap_freebsd.go b/src/cypherpunks.ru/govpn/tap_freebsd.go index 157c583..03d4554 100644 --- a/src/cypherpunks.ru/govpn/tap_freebsd.go +++ b/src/cypherpunks.ru/govpn/tap_freebsd.go @@ -2,7 +2,7 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev */ package govpn diff --git a/src/cypherpunks.ru/govpn/tap_linux.go b/src/cypherpunks.ru/govpn/tap_linux.go index 8c5e883..388853d 100644 --- a/src/cypherpunks.ru/govpn/tap_linux.go +++ b/src/cypherpunks.ru/govpn/tap_linux.go @@ -2,7 +2,7 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev */ package govpn diff --git a/src/cypherpunks.ru/govpn/verifier.go b/src/cypherpunks.ru/govpn/verifier.go index 832fafe..8be6ea7 100644 --- a/src/cypherpunks.ru/govpn/verifier.go +++ b/src/cypherpunks.ru/govpn/verifier.go @@ -1,6 +1,6 @@ /* GoVPN -- simple secure free software virtual private network daemon -Copyright (C) 2014-2016 Sergey Matveev +Copyright (C) 2014-2017 Sergey Matveev 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 @@ -45,14 +45,14 @@ type Verifier struct { 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 { @@ -66,7 +66,7 @@ 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) @@ -95,8 +95,8 @@ func VerifierFromString(input string) (*Verifier, error) { 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 { @@ -113,7 +113,7 @@ func VerifierFromString(input string) (*Verifier, error) { 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[:]), ) } diff --git a/src/github.com/agl/ed25519 b/src/github.com/agl/ed25519 index 278e1ec..5312a61 160000 --- a/src/github.com/agl/ed25519 +++ b/src/github.com/agl/ed25519 @@ -1 +1 @@ -Subproject commit 278e1ec8e8a6e017cd07577924d6766039146ced +Subproject commit 5312a61534124124185d41f09206b9fef1d88403 diff --git a/src/github.com/go-yaml/yaml b/src/github.com/go-yaml/yaml deleted file mode 160000 index e4d366f..0000000 --- a/src/github.com/go-yaml/yaml +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e4d366fc3c7938e2958e662b4258c7a89e1f0e3e diff --git a/src/golang.org/x/crypto b/src/golang.org/x/crypto index b2fa06b..41d678d 160000 --- a/src/golang.org/x/crypto +++ b/src/golang.org/x/crypto @@ -1 +1 @@ -Subproject commit b2fa06b6af4b7c9bfeb8569ab7b17f04550717bf +Subproject commit 41d678d1df78cd0410143162dff954e6dc09300f diff --git a/src/gopkg.in/yaml.v2 b/src/gopkg.in/yaml.v2 new file mode 160000 index 0000000..a5b47d3 --- /dev/null +++ b/src/gopkg.in/yaml.v2 @@ -0,0 +1 @@ +Subproject commit a5b47d31c556af34a302ce5d659e6fea44d90de0 diff --git a/utils/makedist.sh b/utils/makedist.sh index f890c3a..deff778 100755 --- a/utils/makedist.sh +++ b/utils/makedist.sh @@ -10,7 +10,7 @@ repos=" 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 @@ -44,11 +44,13 @@ You can obtain releases source code prepared tarballs on @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" @@ -154,7 +156,7 @@ SHA256 хэш: $hash Идентификатор GPG ключа: 0xF2F59045FFE2F4A1 GoVPN releases Отпечаток: D269 9B73 3C41 2068 D8DA 656E F2F5 9045 FFE2 F4A1 -Пожалуйста все вопросы касающиеся использования GoVPN, отчёты об ошибках +Пожалуйста, все вопросы касающиеся использования GoVPN, отчёты об ошибках и патчи отправляйте в govpn-devel почтовую рассылку: https://lists.cypherpunks.ru/pipermail/govpn-devel/ EOF diff --git a/utils/news.sh b/utils/news.sh new file mode 100755 index 0000000..9064312 --- /dev/null +++ b/utils/news.sh @@ -0,0 +1,33 @@ +#!/bin/sh -ex + +texi=`mktemp` + +cat > $texi < $texi <