From d94f6f7d94e0dfa1ade152d19bd7a07380d95aad Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Tue, 3 Oct 2023 14:37:16 +0200 Subject: [PATCH] plugin: Add support for content blocking in Kubo Fixes #8492. This introduces "nopfs" as a preloaded plugin into Kubo. It automatically make Kubo watch *.deny files found in: - /etc/ipfs/denylists - $XDG_CONFIG_HOME/ipfs/denylists - $IPFS_PATH/denylists (files need to be present before boot in order to be watched). Debug logging can be enabled with `GOLOG_LOG_LEVEL="nopfs=debug"`. All blocks are logged to "nopfs-blocks", so logging requests for blocked content can be achieved with `GOLOG_LOG_LEVEL="nopfs-blocks=info"`. Interactive users will receive the error as response to their commands too. One particularity to keep in mind is that GetMany() will silently drop blocked blocks from the response (an error and a warning are logged). AddMany() will act similarly and avoid adding blocked blocks. --- docs/environment-variables.md | 6 +++ go.mod | 2 + go.sum | 6 +++ plugin/loader/preload.go | 2 + plugin/loader/preload_list | 1 + plugin/plugins/nopfs/nopfs.go | 83 +++++++++++++++++++++++++++++++++++ 6 files changed, 100 insertions(+) create mode 100644 plugin/plugins/nopfs/nopfs.go diff --git a/docs/environment-variables.md b/docs/environment-variables.md index 4113be09b823..f0f6b3f183a7 100644 --- a/docs/environment-variables.md +++ b/docs/environment-variables.md @@ -131,6 +131,12 @@ The above will replace implicit HTTP routers with single one, allowing for inspection/debug of HTTP requests sent by Kubo via `while true ; do nc -l 7423; done` or more advanced tools like [mitmproxy](https://docs.mitmproxy.org/stable/#mitmproxy). + +## `IPFS_CONTENT_BLOCKING_DISABLE` + +Disables the content-blocking subsystem. No denylists will be watched and no +content will be blocked. + ## `LIBP2P_TCP_REUSEPORT` Kubo tries to reuse the same source port for all connections to improve NAT diff --git a/go.mod b/go.mod index e9280f9967b5..2add6398426b 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,8 @@ require ( github.com/fsnotify/fsnotify v1.6.0 github.com/google/uuid v1.3.0 github.com/hashicorp/go-multierror v1.1.1 + github.com/ipfs-shipyard/nopfs v0.0.10 + github.com/ipfs-shipyard/nopfs/ipfs v0.13.1 github.com/ipfs/boxo v0.13.2-0.20231002142647-c28c847582f0 github.com/ipfs/go-block-format v0.1.2 github.com/ipfs/go-cid v0.4.1 diff --git a/go.sum b/go.sum index 441c156ae452..5200b9e15e19 100644 --- a/go.sum +++ b/go.sum @@ -333,6 +333,12 @@ github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY= github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/ipfs-shipyard/nopfs v0.0.9 h1:SkOyf83IAhOuhjYI5Q87TBnDK8SJAeDDZMlcURxq/Uc= +github.com/ipfs-shipyard/nopfs v0.0.9/go.mod h1:zCmxRNQBYwTRYemK6zcKBGLKN9DkDJYNzmNMqw9GtIA= +github.com/ipfs-shipyard/nopfs v0.0.10 h1:kvogvvM5d4YnIlNsTX60KqOPD1Laer6v4YMzYAZsgew= +github.com/ipfs-shipyard/nopfs v0.0.10/go.mod h1:zCmxRNQBYwTRYemK6zcKBGLKN9DkDJYNzmNMqw9GtIA= +github.com/ipfs-shipyard/nopfs/ipfs v0.13.1 h1:Yk3bYIFOUWGeraeusZRohCZXxyiW3yeNByvYV+87gpw= +github.com/ipfs-shipyard/nopfs/ipfs v0.13.1/go.mod h1:awPmwYR98kRsHkrBS0HXGJx4Pe+NStmOa+QfcRgfNUU= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= github.com/ipfs/boxo v0.13.2-0.20231002142647-c28c847582f0 h1:oss04OCg1/QW0h3OfSCZJiUQErpYPOsz7+X4tpgwODs= diff --git a/plugin/loader/preload.go b/plugin/loader/preload.go index 4304862119d7..2ad84e594899 100644 --- a/plugin/loader/preload.go +++ b/plugin/loader/preload.go @@ -7,6 +7,7 @@ import ( pluginfxtest "github.com/ipfs/kubo/plugin/plugins/fxtest" pluginipldgit "github.com/ipfs/kubo/plugin/plugins/git" pluginlevelds "github.com/ipfs/kubo/plugin/plugins/levelds" + pluginnopfs "github.com/ipfs/kubo/plugin/plugins/nopfs" pluginpeerlog "github.com/ipfs/kubo/plugin/plugins/peerlog" ) @@ -22,4 +23,5 @@ func init() { Preload(pluginlevelds.Plugins...) Preload(pluginpeerlog.Plugins...) Preload(pluginfxtest.Plugins...) + Preload(pluginnopfs.Plugins...) } diff --git a/plugin/loader/preload_list b/plugin/loader/preload_list index c18ea80ccd53..462a3f393376 100644 --- a/plugin/loader/preload_list +++ b/plugin/loader/preload_list @@ -11,3 +11,4 @@ flatfs github.com/ipfs/kubo/plugin/plugins/flatfs * levelds github.com/ipfs/kubo/plugin/plugins/levelds * peerlog github.com/ipfs/kubo/plugin/plugins/peerlog * fxtest github.com/ipfs/kubo/plugin/plugins/fxtest * +nopfs github.com/ipfs/kubo/plugin/plugins/nopfs * \ No newline at end of file diff --git a/plugin/plugins/nopfs/nopfs.go b/plugin/plugins/nopfs/nopfs.go new file mode 100644 index 000000000000..a04734187ba2 --- /dev/null +++ b/plugin/plugins/nopfs/nopfs.go @@ -0,0 +1,83 @@ +package nopfs + +import ( + "os" + "path/filepath" + + "github.com/ipfs-shipyard/nopfs" + "github.com/ipfs-shipyard/nopfs/ipfs" + "github.com/ipfs/kubo/config" + "github.com/ipfs/kubo/core" + "github.com/ipfs/kubo/core/node" + "github.com/ipfs/kubo/plugin" + "go.uber.org/fx" +) + +// Plugins sets the list of plugins to be loaded. +var Plugins = []plugin.Plugin{ + &nopfsPlugin{}, +} + +// fxtestPlugin is used for testing the fx plugin. +// It merely adds an fx option that logs a debug statement, so we can verify that it works in tests. +type nopfsPlugin struct{} + +var _ plugin.PluginFx = (*nopfsPlugin)(nil) + +func (p *nopfsPlugin) Name() string { + return "nopfs" +} + +func (p *nopfsPlugin) Version() string { + return "0.0.10" +} + +func (p *nopfsPlugin) Init(env *plugin.Environment) error { + return nil +} + +// MakeBlocker is a factory for the blocker so that it can be provided with Fx. +func MakeBlocker() (*nopfs.Blocker, error) { + ipfsPath, err := config.PathRoot() + if err != nil { + return nil, err + } + + defaultFiles, err := nopfs.GetDenylistFiles() + if err != nil { + return nil, err + } + + kuboFiles, err := nopfs.GetDenylistFilesInDir(filepath.Join(ipfsPath, "denylists")) + if err != nil { + return nil, err + } + + files := append(defaultFiles, kuboFiles...) + + return nopfs.NewBlocker(files) +} + +// PathResolvers returns wrapped PathResolvers for Kubo. +func PathResolvers(fetchers node.FetchersIn, blocker *nopfs.Blocker) node.PathResolversOut { + res := node.PathResolverConfig(fetchers) + return node.PathResolversOut{ + IPLDPathResolver: ipfs.WrapResolver(res.IPLDPathResolver, blocker), + UnixFSPathResolver: ipfs.WrapResolver(res.UnixFSPathResolver, blocker), + } +} + +func (p *nopfsPlugin) Options(info core.FXNodeInfo) ([]fx.Option, error) { + if os.Getenv("IPFS_CONTENT_BLOCKING_DISABLE") != "" { + return info.FXOptions, nil + } + + opts := append( + info.FXOptions, + fx.Provide(MakeBlocker), + fx.Decorate(ipfs.WrapBlockService), + fx.Decorate(ipfs.WrapNameSystem), + fx.Decorate(PathResolvers), + ) + return opts, nil +}