diff --git a/.gitignore b/.gitignore index e1d5e30..01b2cdf 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ bin/* */*.i2pkeys README.md.asc samcatd +*/*.pem +*.pem diff --git a/config/tls.go b/config/tls.go index 25d8582..3610970 100644 --- a/config/tls.go +++ b/config/tls.go @@ -2,7 +2,9 @@ package i2ptunconf import ( "crypto/tls" - "log" + "strings" + + "github.com/eyedeekay/sam-forwarder/tls" ) // GetPort443 takes an argument and a default. If the argument differs from the @@ -62,7 +64,7 @@ func (c *Conf) GetTLSConfig(arg, def string, label ...string) string { if c.Config == nil { return arg } - if x, o := c.Get("cert", label...); o { + if x, o := c.Get("cert.pem", label...); o { return x } return arg @@ -70,7 +72,7 @@ func (c *Conf) GetTLSConfig(arg, def string, label ...string) string { // SetClientDest sets the key name from the config file func (c *Conf) SetTLSConfig(label ...string) { - if v, ok := c.Get("cert", label...); ok { + if v, ok := c.Get("cert.pem", label...); ok { c.Cert = v } else { c.Cert = "" @@ -85,7 +87,7 @@ func (c *Conf) GetTLSConfigPem(arg, def string, label ...string) string { if c.Config == nil { return arg } - if x, o := c.Get("pem", label...); o { + if x, o := c.Get("key.pem", label...); o { return x } return arg @@ -93,17 +95,17 @@ func (c *Conf) GetTLSConfigPem(arg, def string, label ...string) string { // SetClientDest sets the key name from the config file func (c *Conf) SetTLSConfigPem(label ...string) { - if v, ok := c.Get("pem", label...); ok { + if v, ok := c.Get("key.pem", label...); ok { c.Pem = v } else { c.Pem = "" } } -func (c *Conf) TLSConfig() *tls.Config { - cert, err := tls.LoadX509KeyPair(c.Cert, c.Pem) - if err != nil { - log.Fatal(err) +func (c *Conf) TLSConfig() (*tls.Config, error) { + names := []string{c.Base32()} + if c.HostName != "" && strings.HasSuffix(c.HostName, ".i2p") { + names = append(names, c.HostName) } - return &tls.Config{Certificates: []tls.Certificate{cert}} + return i2ptls.TLSConfig(c.Cert, c.Pem, names) } diff --git a/config/tunconf.go b/config/tunconf.go index 56145b4..d984b46 100644 --- a/config/tunconf.go +++ b/config/tunconf.go @@ -70,6 +70,7 @@ type Conf struct { UseTLS bool `default:false` Cert string `default:""` Pem string `default:""` + HostName string `default:""` //TLSConf *tls.Config LoadedKeys i2pkeys.I2PKeys } diff --git a/tcp/forwarder.go b/tcp/forwarder.go index b8ac38c..9a2c34b 100644 --- a/tcp/forwarder.go +++ b/tcp/forwarder.go @@ -361,7 +361,11 @@ func (f *SAMForwarder) Serve() error { log.Println("SAM Listener created,", f.Base32()) log.Println("Human-readable hash:\n ", f.Base32Readable()) if f.Conf.UseTLS { - f.publishListen = tls.NewListener(publishListen, f.Conf.TLSConfig()) + tlsconf, err := f.Conf.TLSConfig() + if err != nil { + return err + } + f.publishListen = tls.NewListener(publishListen, tlsconf) } else { f.publishListen = publishListen } diff --git a/tls/tls.go b/tls/tls.go index 303baf6..94c32ed 100644 --- a/tls/tls.go +++ b/tls/tls.go @@ -8,6 +8,7 @@ import ( "crypto/x509/pkix" "encoding/pem" "log" + "math/big" "os" ) @@ -18,9 +19,15 @@ func CheckFile(path string) bool { return true } -func Certificate(Cert, Pem string, names []string, priv *ed25519.PrivateKey) (*tls.Certificate, error) { +func CertPemificate(CertPem, KeyPem string, names []string, priv ed25519.PrivateKey) (tls.Certificate, error) { + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + log.Fatalf("Failed to generate serial number: %v", err) + } template := x509.Certificate{ - // SerialNumber: serialNumber, + SerialNumber: serialNumber, Subject: pkix.Name{ Organization: []string{"Acme Co"}, }, @@ -30,27 +37,28 @@ func Certificate(Cert, Pem string, names []string, priv *ed25519.PrivateKey) (*t ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true, } - template.DNSNames = append(template.DNSNames, names...) - + if len(names) > 0 { + template.DNSNames = append(template.DNSNames, names...) + } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, priv.Public().(ed25519.PublicKey), priv) if err != nil { log.Fatalf("Failed to create certificate: %v", err) } - certOut, err := os.Create(Cert) + certOut, err := os.Create(CertPem) if err != nil { - log.Fatalf("Failed to open "+Cert+" for writing: %v", err) + log.Fatalf("Failed to open "+CertPem+" for writing: %v", err) } if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil { - log.Fatalf("Failed to write data to "+Cert+": %v", err) + log.Fatalf("Failed to write data to "+CertPem+": %v", err) } if err := certOut.Close(); err != nil { - log.Fatalf("Error closing "+Cert+": %v", err) + log.Fatalf("Error closing "+CertPem+": %v", err) } - log.Print("wrote " + Cert + "\n") + log.Print("wrote " + CertPem + "\n") - keyOut, err := os.OpenFile(Pem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + keyOut, err := os.OpenFile(KeyPem, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { - log.Fatalf("Failed to open "+Pem+" for writing: %v", err) + log.Fatalf("Failed to open "+KeyPem+" for writing: %v", err) } privBytes, err := x509.MarshalPKCS8PrivateKey(priv) if err != nil { @@ -62,25 +70,31 @@ func Certificate(Cert, Pem string, names []string, priv *ed25519.PrivateKey) (*t if err := keyOut.Close(); err != nil { log.Fatalf("Error closing key.pem: %v", err) } - return tls.LoadX509KeyPair(Cert, Pem) + return tls.LoadX509KeyPair(CertPem, KeyPem) } -func TLSConfig(Cert, Pem string, names []string) *tls.Config { - if CheckFile(Cert) && CheckFile(Pem) { - cert, err := tls.LoadX509KeyPair(Cert, Pem) +func TLSConfig(CertPem, KeyPem string, names []string) (*tls.Config, error) { + var ServerName string + if len(names) > 0 { + ServerName = names[0] + } + + if CheckFile(CertPem) && CheckFile(KeyPem) { + cert, err := tls.LoadX509KeyPair(CertPem, KeyPem) if err != nil { - log.Fatal(err) + return nil, err } - return &tls.Config{Certificates: []tls.Certificate{cert}} + + return &tls.Config{Certificates: []tls.Certificate{cert}, ServerName: ServerName}, nil } else { _, priv, err := ed25519.GenerateKey(rand.Reader) if err != nil { - log.Fatal(err) + return nil, err } - cert, err := Certificate(Cert, Pem, names, priv) + cert, err := CertPemificate(CertPem, KeyPem, names, priv) if err != nil { - log.Fatal(err) + return nil, err } - return &tls.Config{Certificates: []tls.Certificate{cert}} + return &tls.Config{Certificates: []tls.Certificate{cert}, ServerName: ServerName}, nil } } diff --git a/tls/tls_test.go b/tls/tls_test.go new file mode 100644 index 0000000..b773857 --- /dev/null +++ b/tls/tls_test.go @@ -0,0 +1,11 @@ +package i2ptls + +import "testing" + +func TestTLSGenerate(t *testing.T) { + config, err := TLSConfig("cert.pem", "key.pem", []string{"idk.i2p"}) + if err != nil { + t.Fatal(err.Error()) + } + t.Log(config.ServerName) +}