Skip to content

Commit

Permalink
plugin: Add support for content blocking in Kubo
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
hsanjuan committed Oct 3, 2023
1 parent 9752747 commit d94f6f7
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 0 deletions.
6 changes: 6 additions & 0 deletions docs/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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=
Expand Down
2 changes: 2 additions & 0 deletions plugin/loader/preload.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand All @@ -22,4 +23,5 @@ func init() {
Preload(pluginlevelds.Plugins...)
Preload(pluginpeerlog.Plugins...)
Preload(pluginfxtest.Plugins...)
Preload(pluginnopfs.Plugins...)
}
1 change: 1 addition & 0 deletions plugin/loader/preload_list
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
83 changes: 83 additions & 0 deletions plugin/plugins/nopfs/nopfs.go
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit d94f6f7

Please sign in to comment.