addrs.go
1 package libp2p 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path/filepath" 8 "time" 9 10 logging "github.com/ipfs/go-log/v2" 11 version "github.com/ipfs/kubo" 12 "github.com/ipfs/kubo/config" 13 p2pforge "github.com/ipshipyard/p2p-forge/client" 14 "github.com/libp2p/go-libp2p" 15 "github.com/libp2p/go-libp2p/core/host" 16 p2pbhost "github.com/libp2p/go-libp2p/p2p/host/basic" 17 ma "github.com/multiformats/go-multiaddr" 18 mamask "github.com/whyrusleeping/multiaddr-filter" 19 20 "github.com/caddyserver/certmagic" 21 "go.uber.org/fx" 22 ) 23 24 func AddrFilters(filters []string) func() (*ma.Filters, Libp2pOpts, error) { 25 return func() (filter *ma.Filters, opts Libp2pOpts, err error) { 26 filter = ma.NewFilters() 27 opts.Opts = append(opts.Opts, libp2p.ConnectionGater((*filtersConnectionGater)(filter))) 28 for _, s := range filters { 29 f, err := mamask.NewMask(s) 30 if err != nil { 31 return filter, opts, fmt.Errorf("incorrectly formatted address filter in config: %s", s) 32 } 33 filter.AddFilter(*f, ma.ActionDeny) 34 } 35 return filter, opts, nil 36 } 37 } 38 39 func makeAddrsFactory(announce []string, appendAnnounce []string, noAnnounce []string) (p2pbhost.AddrsFactory, error) { 40 var err error // To assign to the slice in the for loop 41 existing := make(map[string]bool) // To avoid duplicates 42 43 annAddrs := make([]ma.Multiaddr, len(announce)) 44 for i, addr := range announce { 45 annAddrs[i], err = ma.NewMultiaddr(addr) 46 if err != nil { 47 return nil, err 48 } 49 existing[addr] = true 50 } 51 52 var appendAnnAddrs []ma.Multiaddr 53 for _, addr := range appendAnnounce { 54 if existing[addr] { 55 // skip AppendAnnounce that is on the Announce list already 56 continue 57 } 58 appendAddr, err := ma.NewMultiaddr(addr) 59 if err != nil { 60 return nil, err 61 } 62 appendAnnAddrs = append(appendAnnAddrs, appendAddr) 63 } 64 65 filters := ma.NewFilters() 66 noAnnAddrs := map[string]bool{} 67 for _, addr := range noAnnounce { 68 f, err := mamask.NewMask(addr) 69 if err == nil { 70 filters.AddFilter(*f, ma.ActionDeny) 71 continue 72 } 73 maddr, err := ma.NewMultiaddr(addr) 74 if err != nil { 75 return nil, err 76 } 77 noAnnAddrs[string(maddr.Bytes())] = true 78 } 79 80 return func(allAddrs []ma.Multiaddr) []ma.Multiaddr { 81 var addrs []ma.Multiaddr 82 if len(annAddrs) > 0 { 83 addrs = annAddrs 84 } else { 85 addrs = allAddrs 86 } 87 addrs = append(addrs, appendAnnAddrs...) 88 89 var out []ma.Multiaddr 90 for _, maddr := range addrs { 91 // check for exact matches 92 ok := noAnnAddrs[string(maddr.Bytes())] 93 // check for /ipcidr matches 94 if !ok && !filters.AddrBlocked(maddr) { 95 out = append(out, maddr) 96 } 97 } 98 return out 99 }, nil 100 } 101 102 func AddrsFactory(announce []string, appendAnnounce []string, noAnnounce []string) any { 103 return func(params struct { 104 fx.In 105 ForgeMgr *p2pforge.P2PForgeCertMgr `optional:"true"` 106 }, 107 ) (opts Libp2pOpts, err error) { 108 var addrsFactory p2pbhost.AddrsFactory 109 announceAddrsFactory, err := makeAddrsFactory(announce, appendAnnounce, noAnnounce) 110 if err != nil { 111 return opts, err 112 } 113 if params.ForgeMgr == nil { 114 addrsFactory = announceAddrsFactory 115 } else { 116 addrsFactory = func(multiaddrs []ma.Multiaddr) []ma.Multiaddr { 117 forgeProcessing := params.ForgeMgr.AddressFactory()(multiaddrs) 118 announceProcessing := announceAddrsFactory(forgeProcessing) 119 return announceProcessing 120 } 121 } 122 opts.Opts = append(opts.Opts, libp2p.AddrsFactory(addrsFactory)) 123 return 124 } 125 } 126 127 func ListenOn(addresses []string) any { 128 return func() (opts Libp2pOpts) { 129 return Libp2pOpts{ 130 Opts: []libp2p.Option{ 131 libp2p.ListenAddrStrings(addresses...), 132 }, 133 } 134 } 135 } 136 137 func P2PForgeCertMgr(repoPath string, cfg config.AutoTLS, atlsLog *logging.ZapEventLogger) any { 138 return func() (*p2pforge.P2PForgeCertMgr, error) { 139 storagePath := filepath.Join(repoPath, "p2p-forge-certs") 140 rawLogger := atlsLog.Desugar() 141 142 // TODO: this should not be necessary after 143 // https://github.com/ipshipyard/p2p-forge/pull/42 but keep it here for 144 // now to help tracking down any remaining conditions causing 145 // https://github.com/ipshipyard/p2p-forge/issues/8 146 certmagic.Default.Logger = rawLogger.Named("default_fixme") 147 certmagic.DefaultACME.Logger = rawLogger.Named("default_acme_client_fixme") 148 149 registrationDelay := cfg.RegistrationDelay.WithDefault(config.DefaultAutoTLSRegistrationDelay) 150 if cfg.Enabled == config.True && cfg.RegistrationDelay.IsDefault() { 151 // Skip delay if user explicitly enabled AutoTLS.Enabled in config 152 // and did not set custom AutoTLS.RegistrationDelay 153 registrationDelay = 0 * time.Second 154 } 155 156 certStorage := &certmagic.FileStorage{Path: storagePath} 157 certMgr, err := p2pforge.NewP2PForgeCertMgr( 158 p2pforge.WithLogger(rawLogger.Sugar()), 159 p2pforge.WithForgeDomain(cfg.DomainSuffix.WithDefault(config.DefaultDomainSuffix)), 160 p2pforge.WithForgeRegistrationEndpoint(cfg.RegistrationEndpoint.WithDefault(config.DefaultRegistrationEndpoint)), 161 p2pforge.WithRegistrationDelay(registrationDelay), 162 p2pforge.WithCAEndpoint(cfg.CAEndpoint.WithDefault(config.DefaultCAEndpoint)), 163 p2pforge.WithForgeAuth(cfg.RegistrationToken.WithDefault(os.Getenv(p2pforge.ForgeAuthEnv))), 164 p2pforge.WithUserAgent(version.GetUserAgentVersion()), 165 p2pforge.WithCertificateStorage(certStorage), 166 p2pforge.WithShortForgeAddrs(cfg.ShortAddrs.WithDefault(config.DefaultAutoTLSShortAddrs)), 167 ) 168 if err != nil { 169 return nil, err 170 } 171 172 return certMgr, nil 173 } 174 } 175 176 func StartP2PAutoTLS(lc fx.Lifecycle, certMgr *p2pforge.P2PForgeCertMgr, h host.Host) { 177 lc.Append(fx.Hook{ 178 OnStart: func(ctx context.Context) error { 179 certMgr.ProvideHost(h) 180 return certMgr.Start() 181 }, 182 OnStop: func(ctx context.Context) error { 183 certMgr.Stop() 184 return nil 185 }, 186 }) 187 }