From 57065323c4913d017b1a2a014c2380c833ae6e00 Mon Sep 17 00:00:00 2001 From: idk Date: Thu, 27 Jun 2019 19:49:05 -0400 Subject: [PATCH] HTTPS-enabled onion reseeds --- README.md | 6 ++ cmd/reseed.go | 93 +++++++++++++------ history.txt | 3 + main.go | 6 +- reseed/server.go | 72 +++++++++++--- .../gorilla/handlers/proxy_headers_test.go | 18 ++-- 6 files changed, 144 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 9a5b341..340dad2 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,12 @@ i2p-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --tlsHost=yo i2p-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --onion ``` +### Without a webserver, standalone, automatic OnionV3 with TLS support + +``` +i2p-tools reseed --signer=you@mail.i2p --netdb=/home/i2p/.i2p/netDb --tlsHost=your-domain.tld --onion +``` + If this is your first time running a reseed server (ie. you don't have any existing keys), you can simply run the command and follow the prompts to create the appropriate keys, crl and certificates. Afterwards an HTTPS reseed server will start on the default port and generate 6 files in your current directory diff --git a/cmd/reseed.go b/cmd/reseed.go index e28fc92..f58ab50 100644 --- a/cmd/reseed.go +++ b/cmd/reseed.go @@ -124,6 +124,10 @@ func reseedAction(c *cli.Context) { var tlsCert, tlsKey string tlsHost := c.String("tlsHost") + if c.Bool("onion") { + tlsHost = "onion" + } + if tlsHost != "" { tlsKey = c.String("tlsKey") // if no key is specified, default to the host.pem in the current dir @@ -208,35 +212,70 @@ func reseedAction(c *cli.Context) { if err != nil { log.Fatalln(err.Error()) } else { - log.Fatalln( - server.ListenAndServeOnion( - nil, - &tor.ListenConf{ - LocalPort: port, - Key: ed25519.PrivateKey(ok), - RemotePorts: []int{80}, - Version3: true, - NonAnonymous: c.Bool("singleOnion"), - DiscardKey: false, - }, - c.String("onionKey"), - ), - ) + if tlsCert != "" && tlsKey != "" { + log.Fatalln( + server.ListenAndServeOnionTLS( + nil, + &tor.ListenConf{ + LocalPort: port, + Key: ed25519.PrivateKey(ok), + RemotePorts: []int{443}, + Version3: true, + NonAnonymous: c.Bool("singleOnion"), + DiscardKey: false, + }, + tlsCert, tlsKey, + c.String("onionKey"), + ), + ) + }else{ + log.Fatalln( + server.ListenAndServeOnion( + nil, + &tor.ListenConf{ + LocalPort: port, + Key: ed25519.PrivateKey(ok), + RemotePorts: []int{80}, + Version3: true, + NonAnonymous: c.Bool("singleOnion"), + DiscardKey: false, + }, + c.String("onionKey"), + ), + ) + } } } else if os.IsNotExist(err) { - log.Fatalln( - server.ListenAndServeOnion( - nil, - &tor.ListenConf{ - LocalPort: port, - RemotePorts: []int{80}, - Version3: true, - NonAnonymous: c.Bool("singleOnion"), - DiscardKey: false, - }, - c.String("onionKey"), - ), - ) + if tlsCert != "" && tlsKey != "" { + log.Fatalln( + server.ListenAndServeOnionTLS( + nil, + &tor.ListenConf{ + LocalPort: port, + RemotePorts: []int{443}, + Version3: true, + NonAnonymous: c.Bool("singleOnion"), + DiscardKey: false, + }, + tlsCert, tlsKey, + c.String("onionKey"), + ), + ) + }else{ + log.Fatalln( + server.ListenAndServeOnion( + nil, + &tor.ListenConf{ + LocalPort: port, + RemotePorts: []int{80}, + Version3: true, + NonAnonymous: c.Bool("singleOnion"), + DiscardKey: false, + }, + c.String("onionKey"), + ), + ) + } } else { } diff --git a/history.txt b/history.txt index 0cd9171..fd69f27 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,6 @@ +2019-06-27 + * automatically configuring Tor Onionv3 Server + 2019-04-21 * app.Version = "0.1.7" * enabling TLS 1.3 *only* diff --git a/main.go b/main.go index 5b4c87d..5be5540 100644 --- a/main.go +++ b/main.go @@ -9,9 +9,9 @@ import ( ) func main() { - // TLS 1.3 is available only on an opt-in basis in Go 1.12. - // To enable it, set the GODEBUG environment variable (comma-separated key=value options) such that it includes "tls13=1". - // To enable it from within the process, set the environment variable before any use of TLS: + // TLS 1.3 is available only on an opt-in basis in Go 1.12. + // To enable it, set the GODEBUG environment variable (comma-separated key=value options) such that it includes "tls13=1". + // To enable it from within the process, set the environment variable before any use of TLS: os.Setenv("GODEBUG", os.Getenv("GODEBUG")+",tls13=1") // use at most half the cpu cores diff --git a/reseed/server.go b/reseed/server.go index 7c6c49d..af33f10 100644 --- a/reseed/server.go +++ b/reseed/server.go @@ -15,10 +15,10 @@ import ( "github.com/cretz/bine/tor" "github.com/cretz/bine/torutil/ed25519" - "github.com/throttled/throttled" - "github.com/throttled/throttled/store" "github.com/gorilla/handlers" "github.com/justinas/alice" + "github.com/throttled/throttled" + "github.com/throttled/throttled/store" ) const ( @@ -34,18 +34,18 @@ type Server struct { func NewServer(prefix string, trustProxy bool) *Server { config := &tls.Config{ -// MinVersion: tls.VersionTLS10, -// PreferServerCipherSuites: true, -// CipherSuites: []uint16{ -// tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, -// tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, -// tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, -// tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, -// tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, -// tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, -// tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, -// tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, -// }, + // MinVersion: tls.VersionTLS10, + // PreferServerCipherSuites: true, + // CipherSuites: []uint16{ + // tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + // tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + // tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + // tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + // tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + // tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + // tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + // tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + // }, MinVersion: tls.VersionTLS13, PreferServerCipherSuites: true, CipherSuites: []uint16{ @@ -122,8 +122,50 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error { return srv.Serve(tlsListener) } +func (srv *Server) ListenAndServeOnionTLS(startConf *tor.StartConf, listenConf *tor.ListenConf, certFile, keyFile, onionKey string) error { + log.Println("Starting and registering OnionV3 HTTPS service, please wait a couple of minutes...") + tor, err := tor.Start(nil, startConf) + if err != nil { + return err + } + defer tor.Close() + + listenCtx, listenCancel := context.WithTimeout(context.Background(), 3*time.Minute) + defer listenCancel() + + if srv.TLSConfig == nil { + srv.TLSConfig = &tls.Config{} + } + + if srv.TLSConfig.NextProtos == nil { + srv.TLSConfig.NextProtos = []string{"http/1.1"} + } + srv.OnionListener, err = tor.Listen(listenCtx, listenConf) + if err != nil { + return err + } + srv.Addr = srv.OnionListener.ID + + // var err error + srv.TLSConfig.Certificates = make([]tls.Certificate, 1) + srv.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) + if err != nil { + return err + } + + err = ioutil.WriteFile(onionKey, []byte(srv.OnionListener.Key.(ed25519.KeyPair).PrivateKey()), 0644) + if err != nil { + return err + } + log.Printf("Onionv3 server started on https://%v.onion\n", srv.OnionListener.ID) + + tlsListener := tls.NewListener(srv.OnionListener, srv.TLSConfig) + + return srv.Serve(tlsListener) +} + func (srv *Server) ListenAndServeOnion(startConf *tor.StartConf, listenConf *tor.ListenConf, onionKey string) error { - log.Println("Starting and registering onion service, please wait a couple of minutes...") + log.Println("Starting and registering OnionV3 service, please wait a couple of minutes...") tor, err := tor.Start(nil, startConf) if err != nil { return err diff --git a/vendor/github.com/gorilla/handlers/proxy_headers_test.go b/vendor/github.com/gorilla/handlers/proxy_headers_test.go index 1bd7805..b1fe685 100644 --- a/vendor/github.com/gorilla/handlers/proxy_headers_test.go +++ b/vendor/github.com/gorilla/handlers/proxy_headers_test.go @@ -14,15 +14,15 @@ type headerTable struct { func TestGetIP(t *testing.T) { headers := []headerTable{ - {xForwardedFor, "8.8.8.8", "8.8.8.8"}, // Single address - {xForwardedFor, "8.8.8.8, 8.8.4.4", "8.8.8.8"}, // Multiple - {xForwardedFor, "[2001:db8:cafe::17]:4711", "[2001:db8:cafe::17]:4711"}, // IPv6 address - {xForwardedFor, "", ""}, // None - {xRealIP, "8.8.8.8", "8.8.8.8"}, // Single address - {xRealIP, "8.8.8.8, 8.8.4.4", "8.8.8.8, 8.8.4.4"}, // Multiple - {xRealIP, "[2001:db8:cafe::17]:4711", "[2001:db8:cafe::17]:4711"}, // IPv6 address - {xRealIP, "", ""}, // None - {forwarded, `for="_gazonk"`, "_gazonk"}, // Hostname + {xForwardedFor, "8.8.8.8", "8.8.8.8"}, // Single address + {xForwardedFor, "8.8.8.8, 8.8.4.4", "8.8.8.8"}, // Multiple + {xForwardedFor, "[2001:db8:cafe::17]:4711", "[2001:db8:cafe::17]:4711"}, // IPv6 address + {xForwardedFor, "", ""}, // None + {xRealIP, "8.8.8.8", "8.8.8.8"}, // Single address + {xRealIP, "8.8.8.8, 8.8.4.4", "8.8.8.8, 8.8.4.4"}, // Multiple + {xRealIP, "[2001:db8:cafe::17]:4711", "[2001:db8:cafe::17]:4711"}, // IPv6 address + {xRealIP, "", ""}, // None + {forwarded, `for="_gazonk"`, "_gazonk"}, // Hostname {forwarded, `For="[2001:db8:cafe::17]:4711`, `[2001:db8:cafe::17]:4711`}, // IPv6 address {forwarded, `for=192.0.2.60;proto=http;by=203.0.113.43`, `192.0.2.60`}, // Multiple params {forwarded, `for=192.0.2.43, for=198.51.100.17`, "192.0.2.43"}, // Multiple params