diff --git a/README.md b/README.md index f2f5b8b..9c9efa5 100644 --- a/README.md +++ b/README.md @@ -37,46 +37,37 @@ var garlic, i2perr = onramp.NewGarlic("gitea-i2p", "127.0.0.1:7656", onramp.OPT_ var torInstance, torerr = tor.Start(nil, nil) var onion, onionerr = torInstance.Listen(nil, 80) -// This implements the GetListener function for multiple protocols +// This implements the GetListener function for I2P. Note the exemption for Unix sockets. func MultiGetListener(network, address string) (net.Listener, error) { // Add a deferral to say that we've tried to grab a listener defer GetManager().InformCleanup() switch network { - case "tcp", "tcp4", "tcp6": - // Regular TLS listener for clearnet access - return DefaultGetListener(network, address) - case "i2p", "i2pt": - // I2P hidden service listener - return garlic.Listen() - case "onion": - // Tor onion service listener - return onion, nil case "unix", "unixpacket": - // Unix sockets handled normally - unixAddr, err := net.ResolveUnixAddr(network, address) + // I2P isn't really a replacement for the stuff you use Unix sockets for and it's also not an anonymity risk, so treat them normally + unixAddr, err := ResolveUnixAddr(network, address) if err != nil { return nil, err } - return GetListenerUnix(network, unixAddr) + return GetListenerUnixWrapper(network, unixAddr) default: - return nil, net.UnknownNetworkError(network) + return mirror.Listen("tcp", address, "./certs", true) } } // We use `init() to ensure that the appropriate Listeners and Dialers are correctly placed at runtime +// We use `init() to ensure that the I2P Listeners and Dialers are correctly placed at runtime` func init() { - if i2perr != nil { - panic(i2perr) - } - if torerr != nil || onionerr != nil { - panic("Tor setup failed") - } - GetListener = MultiGetListener - - // Configure the HTTP clients for each protocol - // Default remains as-is for TLS connections + /*httpClient := &http.Client{ + Transport: &http.Transport{ + Dial: garlic.Dial, + }, + } + + http.DefaultClient = httpClient + http.DefaultTransport = httpClient.Transport*/ } + ``` Caveats diff --git a/net_mirror.go b/net_mirror.go index b1c1c02..09ce23a 100644 --- a/net_mirror.go +++ b/net_mirror.go @@ -2,13 +2,25 @@ package graceful import ( + "fmt" "net" + "net/http" + "net/url" + "os" + "strings" "github.com/go-i2p/go-meta-listener/mirror" ) -// This implements the GetListener function for I2P. Note the exemption for Unix sockets. +// This implements the GetListener function for TLS, I2P, and Onion. Note the exemption for Unix sockets. func MultiGetListener(network, address string) (net.Listener, error) { + EMAIL, err := os.Getenv("EMAIL") + if err != nil { + return nil, err + } + if EMAIL == "" { + return nil, fmt.Errorf("EMAIL environment variable not set, TLS not possible") + } // Add a deferral to say that we've tried to grab a listener defer GetManager().InformCleanup() switch network { @@ -20,19 +32,43 @@ func MultiGetListener(network, address string) (net.Listener, error) { } return GetListenerUnixWrapper(network, unixAddr) default: - return mirror.Listen("tcp", address, "./certs", true) + return mirror.Listen(address, EMAIL, "./certs", true) } } -// We use `init() to ensure that the I2P Listeners and Dialers are correctly placed at runtime` +// We use `init() to ensure that the appropriate Listeners and Dialers are correctly placed at runtime func init() { GetListener = MultiGetListener - /*httpClient := &http.Client{ + httpClient := &http.Client{ Transport: &http.Transport{ - Dial: garlic.Dial, + Dial: Dial, }, } http.DefaultClient = httpClient - http.DefaultTransport = httpClient.Transport*/ + http.DefaultTransport = httpClient.Transport +} + +func Dial(network, addr string) (net.Conn, error) { + // convert the addr to a URL + url, err := url.Parse(addr) + if err != nil { + return nil, err + } + // get the domain name + domain := url.Hostname() + // get the top-level domain + fr := strings.Split(domain, ".") + tld := fr[len(fr)-1] + switch tld { + case "i2p": + // I2P is a special case, we need to use the garlic dialer + return Garlic.Dial(addr) + case "onion": + // Onion is a special case, we need to use the onion dialer + return Onion.Dial(addr) + default: + // For everything else, we can use the default dialer + return net.Dial(network, addr) + } } diff --git a/net_mirror_dialer.go b/net_mirror_dialer.go new file mode 100644 index 0000000..15c2d15 --- /dev/null +++ b/net_mirror_dialer.go @@ -0,0 +1,42 @@ +package graceful + +import ( + "net" + "net/url" + "strings" + + "github.com/go-i2p/onramp" +) + +var Garlic, GarlicErr = onramp.NewGarlic("git-looseleaf", "127.0.0.1:7656", onramp.OPT_WIDE) +var Onion, OnionErr = onramp.NewOnion("git-looseleaf") + +func Dial(network, addr string) (net.Conn, error) { + // convert the addr to a URL + url, err := url.Parse(addr) + if err != nil { + return nil, err + } + // get the domain name + domain := url.Hostname() + // get the top-level domain + fr := strings.Split(domain, ".") + tld := fr[len(fr)-1] + switch tld { + case "i2p": + if GarlicErr != nil { + return nil, GarlicErr + } + // I2P is a special case, we need to use the garlic dialer + return Garlic.Dial("i2p", addr) + case "onion": + if OnionErr != nil { + return nil, OnionErr + } + // Onion is a special case, we need to use the onion dialer + return Onion.Dial("onion", addr) + default: + // For everything else, we can use the default dialer + return net.Dial(network, addr) + } +}