Documentation ¶
Overview ¶
Package nopfs implements content blocking for the IPFS stack.
nopfs provides an implementation of the compact denylist format (IPIP-383), with methods to check whether IPFS paths and CIDs are blocked.
In order to seamlessly be inserted into the IPFS stack, content-blocking wrappers for several components are provided (BlockService, NameSystem, Resolver...). A Kubo plugin (see kubo/) can be used to give Kubo content-blocking superpowers.
Index ¶
- Variables
- func GetDenylistFiles() ([]string, error)
- func GetDenylistFilesInDir(dirpath string) ([]string, error)
- type BlockedPath
- type Blocker
- type BlocksDB
- type Denylist
- func (dl *Denylist) Close() error
- func (dl *Denylist) IsCidBlocked(c cid.Cid) StatusResponse
- func (dl *Denylist) IsIPFSPathBlocked(cidStr, subpath string) StatusResponse
- func (dl *Denylist) IsIPLDPathBlocked(cidStr, subpath string) StatusResponse
- func (dl *Denylist) IsIPNSPathBlocked(name, subpath string) StatusResponse
- func (dl *Denylist) IsPathBlocked(p path.Path) StatusResponse
- func (dl *Denylist) IsSubpathBlocked(subpath string) StatusResponse
- type DenylistHeader
- type Entries
- type Entry
- type HTTPSubscriber
- type Status
- type StatusError
- type StatusResponse
Constants ¶
This section is empty.
Variables ¶
var ErrHeaderNotFound = errors.New("header not found")
ErrHeaderNotFound is returned when no header can be Decoded.
var SafeCids = map[cid.Cid]string{
cid.MustParse("QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"): "empty unixfs directory",
cid.MustParse("bafyaabakaieac"): "empty unixfs directory inlined",
cid.MustParse("bafkreihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku"): "empty block",
cid.MustParse("bafkqaaa"): "empty block inlined",
cid.MustParse("QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH"): "empty block dag-pb",
cid.MustParse("bafyreigbtj4x7ip5legnfznufuopl4sg4knzc2cof6duas4b3q2fy6swua"): "empty block dag-cbor",
cid.MustParse("baguqeeraiqjw7i2vwntyuekgvulpp2det2kpwt6cd7tx5ayqybqpmhfk76fa"): "empty block dag-json",
}
SafeCids is a map of known, innoffensive CIDs that correspond to empty-blocks or empty-directories. Blocking these can break applications so they are ignored (with a warning), when they appear on a denylist.
Functions ¶
func GetDenylistFiles ¶
GetDenylistFiles returns a list of ".deny" files found in $XDG_CONFIG_HOME/ipfs/denylists and /etc/ipfs/denylists. The files are sortered by their names in their respective directories.
func GetDenylistFilesInDir ¶
GetDenylistFilesInDir returns a list of ".deny" files found in the given directory. The files are sortered by their names. It returns an empty list and no error if the directory does not exist.
Types ¶
type BlockedPath ¶
BlockedPath represents the path part of a blocking rule.
func NewBlockedPath ¶
func NewBlockedPath(rawPath string) (BlockedPath, error)
NewBlockedPath takes a raw path, unscapes and sanitizes it, detecting and handling wildcards. It may also represent an "allowed" path on "allowed" rules.
func (BlockedPath) Matches ¶
func (bpath BlockedPath) Matches(path string) bool
Matches returns whether the given path matched the blocked (or allowed) path.
type Blocker ¶
A Blocker binds together multiple Denylists and can decide whether a path or a CID is blocked.
func NewBlocker ¶
NewBlocker creates a Blocker using the given denylist file paths. For default denylist locations, you can use GetDenylistFiles(). TODO: Options.
func (*Blocker) IsCidBlocked ¶
func (blocker *Blocker) IsCidBlocked(c cid.Cid) StatusResponse
IsCidBlocked returns blocking status for a CID. A CID is blocked when a Denylist reports it as blocked. A CID is not blocked when no denylist reports it as blocked or it is explicitally allowed. Lookup stops as soon as a defined "blocked" or "allowed" status is found.
Lookup for "allowed" or "blocked" status happens in order of the denylist, thus the denylist position during Blocker creation affects which one has preference.
Note that StatusResponse.Path will be unset. See Denylist.IsCidBlocked() for more info.
func (*Blocker) IsPathBlocked ¶
func (blocker *Blocker) IsPathBlocked(p path.Path) StatusResponse
IsPathBlocked returns blocking status for an IPFS Path. A Path is blocked when a Denylist reports it as blocked. A Path is not blocked when no denylist reports it as blocked or it is explicitally allowed. Lookup stops as soon as a defined "blocked" or "allowed" status is found.
Lookup for "allowed" or "blocked" status happens in order of the denylist, thus the denylist position during Blocker creation affects which one has preference.
Note that StatusResponse.Cid will be unset. See Denylist.IsPathBlocked() for more info.
type BlocksDB ¶
type BlocksDB struct {
// contains filtered or unexported fields
}
BlocksDB is a key-value store of Entries. Keying may vary depending on whether we are indexing IPNS names, CIDs etc.
type Denylist ¶
type Denylist struct { Header DenylistHeader Filename string Entries Entries IPFSBlocksDB *BlocksDB IPNSBlocksDB *BlocksDB DoubleHashBlocksDB map[uint64]*BlocksDB // mhCode -> blocks using that code PathBlocksDB *BlocksDB PathPrefixBlocks Entries // contains filtered or unexported fields }
A Denylist represents a denylist file and its rules. It can parse and follow a denylist file, and can answer questions about blocked or allowed items in this denylist.
func NewDenylist ¶
NewDenylist opens a denylist file and processes it (parses all its entries).
If follow is false, the file handle is closed.
If follow is true, the denylist file will be followed upon return. Any appended rules will be processed live-updated in the denylist. Denylist.Close() should be used when the Denylist or the following is no longer needed.
func NewDenylistReader ¶
func NewDenylistReader(r io.ReadSeekCloser) (*Denylist, error)
NewDenylistReader processes a denylist from the given reader (parses all its entries).
func (*Denylist) Close ¶
Close closes the Denylist file handle and stops watching write events on it.
func (*Denylist) IsCidBlocked ¶
func (dl *Denylist) IsCidBlocked(c cid.Cid) StatusResponse
IsCidBlocked provides Blocking Status for a given CID. This is done by extracting the multihash and checking if it is blocked by any rule.
func (*Denylist) IsIPFSPathBlocked ¶
func (dl *Denylist) IsIPFSPathBlocked(cidStr, subpath string) StatusResponse
IsIPFSPathBlocked returns Blocking Status for a given IPFS CID and its subpath. The cidStr is NOT an "/ipns/cid" path, but just the cid.
func (*Denylist) IsIPLDPathBlocked ¶
func (dl *Denylist) IsIPLDPathBlocked(cidStr, subpath string) StatusResponse
IsIPLDPathBlocked returns Blocking Status for a given IPLD CID and its subpath. The cidStr is NOT an "/ipld/cid" path, but just the cid.
func (*Denylist) IsIPNSPathBlocked ¶
func (dl *Denylist) IsIPNSPathBlocked(name, subpath string) StatusResponse
IsIPNSPathBlocked returns Blocking Status for a given IPNS name and its subpath. The name is NOT an "/ipns/name" path, but just the name.
func (*Denylist) IsPathBlocked ¶
func (dl *Denylist) IsPathBlocked(p path.Path) StatusResponse
IsPathBlocked provides Blocking Status for a given path. This is done by interpreting the full path and checking for blocked Path, IPFS, IPNS or double-hashed items matching it.
Matching is more efficient if:
Paths in the form of /ipfs/Qm/... (sha2-256-multihash) are used rather than CIDv1.
A single double-hashing pattern is used.
A small number of path-only match rules using prefixes are used.
func (*Denylist) IsSubpathBlocked ¶
func (dl *Denylist) IsSubpathBlocked(subpath string) StatusResponse
IsSubpathBlocked returns Blocking Status for the given subpath.
type DenylistHeader ¶
type DenylistHeader struct { Version int Name string Description string Author string Hints map[string]string // contains filtered or unexported fields }
DenylistHeader represents the header of a Denylist file.
func (*DenylistHeader) Decode ¶
func (h *DenylistHeader) Decode(r io.Reader) error
Decode decodes a DenlistHeader from a reader. Per the specification, the maximum size of a header is 1KiB. If no header is found, ErrHeaderNotFound is returned.
func (DenylistHeader) String ¶
func (h DenylistHeader) String() string
String provides a short string summary of the Header.
type Entry ¶
type Entry struct { Line uint64 AllowRule bool Hints map[string]string RawValue string Multihash multihash.Multihash // set for ipfs-paths mostly. Path BlockedPath }
Entry represents a rule (or a line) in a denylist file.
type HTTPSubscriber ¶
type HTTPSubscriber struct {
// contains filtered or unexported fields
}
HTTPSubscriber represents a type that subscribes to a remote URL and appends data to a local file.
func NewHTTPSubscriber ¶
func NewHTTPSubscriber(remoteURL, localFile string, interval time.Duration) (*HTTPSubscriber, error)
NewHTTPSubscriber creates a new Subscriber instance with the given parameters.
type Status ¶
type Status int
Status represent represents whether an item is blocked, allowed or simply not found in a Denylist.
type StatusError ¶
type StatusError struct {
Response StatusResponse
}
StatusError implements the error interface and can be used to provide information about a blocked-status in the form of an error.
func (*StatusError) Error ¶
func (err *StatusError) Error() string
type StatusResponse ¶
type StatusResponse struct { Cid cid.Cid Path path.Path Status Status Filename string Entry Entry Error error }
StatusResponse provides full information for a content-block lookup, including the Filename and the Entry, when an associated rule is found.
func (StatusResponse) String ¶
func (r StatusResponse) String() string
String provides a string with the details of a StatusResponse.
func (StatusResponse) ToError ¶
func (r StatusResponse) ToError() *StatusError
ToError returns nil if the Status of the StatusResponse is Allowed or Not Found. When the status is Blocked or Errored, it returns a StatusError.