From 10f2e7fb1837b7896383cc72b7a54d03642053a4 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Sat, 2 May 2015 01:26:39 +0300 Subject: [PATCH] Ability to generate Constant Packet Rate traffic Signed-off-by: Sergey Matveev --- TODO | 2 -- cmd/govpn-client/main.go | 2 ++ cmd/govpn-server/main.go | 2 ++ cpr.go | 24 ++++++++++++++++++++++++ doc/cpr.texi | 10 ++++++++++ doc/overview.texi | 5 +++++ doc/user.texi | 3 +++ transport.go | 9 +++++++++ 8 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 cpr.go create mode 100644 doc/cpr.texi diff --git a/TODO b/TODO index 63d6ef3..e1d3d3f 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,4 @@ * Increase performance -* Implement rate-control * Probably implement alternative Secure Remote Password protocol to allow human memorized passphrases to be used * Randomize ports usage -* Fragmentize packets, noise the traffic diff --git a/cmd/govpn-client/main.go b/cmd/govpn-client/main.go index f6ca4b3..9d99f08 100644 --- a/cmd/govpn-client/main.go +++ b/cmd/govpn-client/main.go @@ -42,6 +42,7 @@ var ( nonceDiff = flag.Int("noncediff", 1, "Allow nonce difference") timeoutP = flag.Int("timeout", 60, "Timeout seconds") noisy = flag.Bool("noise", false, "Enable noise appending") + cpr = flag.Int("cpr", 0, "Enable constant KiB/s out traffic rate") ) func main() { @@ -54,6 +55,7 @@ func main() { govpn.Timeout = time.Second * time.Duration(timeout) govpn.Noncediff = *nonceDiff govpn.NoiseEnable = *noisy + govpn.CPRInit(*cpr) id := govpn.IDDecode(*IDRaw) govpn.PeersInitDummy(id) diff --git a/cmd/govpn-server/main.go b/cmd/govpn-server/main.go index 16462b7..ffb6d23 100644 --- a/cmd/govpn-server/main.go +++ b/cmd/govpn-server/main.go @@ -40,6 +40,7 @@ var ( nonceDiff = flag.Int("noncediff", 1, "Allow nonce difference") timeoutP = flag.Int("timeout", 60, "Timeout seconds") noisy = flag.Bool("noise", false, "Enable noise appending") + cpr = flag.Int("cpr", 0, "Enable constant KiB/s out traffic rate") ) type PeerReadyEvent struct { @@ -87,6 +88,7 @@ func main() { govpn.Timeout = timeout govpn.Noncediff = *nonceDiff govpn.NoiseEnable = *noisy + govpn.CPRInit(*cpr) govpn.PeersInit(*peersPath) bind, err := net.ResolveUDPAddr("udp", *bindAddr) diff --git a/cpr.go b/cpr.go new file mode 100644 index 0000000..1b3c1a4 --- /dev/null +++ b/cpr.go @@ -0,0 +1,24 @@ +package govpn + +import ( + "net" + "time" +) + +type UDPCPR net.UDPConn + +var ( + cprCycle time.Duration + cprEnable bool = false +) + +// Initialize Constant Packet Rate. rate is KiB/s. +func CPRInit(rate int) { + if rate <= 0 { + return + } + NoiseEnable = true + cprEnable = true + cprCycle = time.Second / time.Duration(rate*(1<<10)/MTU) + heartbeatPeriod = cprCycle +} diff --git a/doc/cpr.texi b/doc/cpr.texi new file mode 100644 index 0000000..70572bf --- /dev/null +++ b/doc/cpr.texi @@ -0,0 +1,10 @@ +@node CPR +@section CPR + +Constant Packet Rate is used to hide fact of underlying payload packets +appearance. In this mode daemon inserts necessary dummy packets and +delays other ones. + +This mode is turned by @code{-cpr} option, where you specify desired +outgoing traffic rate in KiB/s (kibibytes per second). This option also +forces using of the @ref{Noise}! It is turned off by default. diff --git a/doc/overview.texi b/doc/overview.texi index 406ab28..517e0e7 100644 --- a/doc/overview.texi +++ b/doc/overview.texi @@ -30,6 +30,10 @@ Server can work with several clients simultaneously. Each client is @strong{identified} by 128-bit key, that does not leak during handshake and each client stays @strong{anonymous} for MiTM and DPI. +Optional ability to hide payload packets lengths by appending +@strong{noise} to them during transmission. Ability to generate constant +packet rate traffic (@strong{CPR}) that will hide even the fact of +packets appearance. The only platform specific requirement is TAP network interface support. API to that kind of device is different, OS dependent and non portable. @@ -57,6 +61,7 @@ network interfaces on top of UDP entirely @item Built-in rehandshake and heartbeat features @item Several simultaneous clients support @item Hiding of payload packets length by noise appending +@item Hiding of payload packets appearance with constant packet rate traffic @item Optional built-in HTTP-server for retrieving information about known connected peers in @url{http://json.org/, JSON} format @end itemize diff --git a/doc/user.texi b/doc/user.texi index b5ebd8f..075f299 100644 --- a/doc/user.texi +++ b/doc/user.texi @@ -18,6 +18,7 @@ automate it using up and down shell scripts. * Server part:: * Stats:: * Noise:: +* CPR:: * Example usage:: @end menu @@ -35,4 +36,6 @@ automate it using up and down shell scripts. @include noise.texi +@include cpr.texi + @include example.texi diff --git a/transport.go b/transport.go index 904d3f1..7379d68 100644 --- a/transport.go +++ b/transport.go @@ -57,6 +57,7 @@ type Peer struct { NonceCipher *xtea.Cipher `json:"-"` LastPing time.Time LastSent time.Time + willSentCycle time.Time buf []byte tag *[poly1305.TagSize]byte keyAuth *[KeySize]byte @@ -314,6 +315,14 @@ func (p *Peer) EthProcess(ethPkt []byte, conn WriteToer, ready chan struct{}) { p.BytesOut += int64(len(p.frame) + poly1305.TagSize) p.FramesOut++ + + if cprEnable { + p.willSentCycle = p.LastSent.Add(cprCycle) + if p.willSentCycle.After(now) { + time.Sleep(p.willSentCycle.Sub(now)) + now = p.willSentCycle + } + } p.LastSent = now if _, err := conn.WriteTo(append(p.frame, p.tag[:]...), p.Addr); err != nil { log.Println("Error sending UDP", err) -- 2.44.0