/ core / node / libp2p / addrs.go
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  }