Documentation ¶
Index ¶
- Constants
- Variables
- func Cause(e error) (string, error)
- func IsKnownMechanism(s string) bool
- func NewMiekgDNSResolver(addr string, opts ...MiekgDNSResolverOption) (*miekgDNSResolver, error)
- func NewPTRAddress(address string) string
- func NewSpfError(k spferr.Kind, e error, t *token) error
- func NormalizeFQDN(name string) string
- func Unwrap(e error) (*token, error, bool)
- type CacheDump
- type DNSResolver
- func (r *DNSResolver) Exists(name string) (bool, *ResponseExtras, error)
- func (r *DNSResolver) LookupPTR(name string) ([]string, *ResponseExtras, error)
- func (r *DNSResolver) LookupTXT(name string) ([]string, *ResponseExtras, error)
- func (r *DNSResolver) LookupTXTStrict(name string) ([]string, *ResponseExtras, error)
- func (r *DNSResolver) MatchIP(name string, matcher IPMatcherFunc) (bool, *ResponseExtras, error)
- func (r *DNSResolver) MatchMX(name string, matcher IPMatcherFunc) (bool, *ResponseExtras, error)
- type DomainError
- type IPMatcherFunc
- type LimitedResolver
- func (r *LimitedResolver) Exists(name string) (bool, *ResponseExtras, error)
- func (r *LimitedResolver) LookupPTR(name string) ([]string, *ResponseExtras, error)
- func (r *LimitedResolver) LookupTXT(name string) ([]string, *ResponseExtras, error)
- func (r *LimitedResolver) LookupTXTStrict(name string) ([]string, *ResponseExtras, error)
- func (r *LimitedResolver) MatchIP(name string, matcher IPMatcherFunc) (bool, *ResponseExtras, error)
- func (r *LimitedResolver) MatchMX(name string, matcher IPMatcherFunc) (bool, *ResponseExtras, error)
- type Listener
- type MiekgDNSResolverOption
- type Option
- type PolicyDeploymentError
- type Resolver
- type ResponseExtras
- type Result
- type RetryResolverOption
- type SpfError
- type Trace
Constants ¶
const UnknownModifierMech = ":?"
UnknownModifierMech constructed so we break policy if someone tries to create a policy out of mechanism string function instead of using actual key
Variables ¶
var ( ErrDNSTemperror = errors.New("temporary DNS error") ErrDNSPermerror = errors.New("permanent DNS error") ErrDNSLimitExceeded = errors.New("limit exceeded") ErrDNSVoidLookupLimitExceeded = errors.New("void lookup limit exceeded") ErrSPFNotFound = errors.New("SPF record not found") ErrInvalidCIDRLength = errors.New("invalid CIDR length") ErrTooManySPFRecords = errors.New("too many SPF records") ErrTooManyRedirects = errors.New(`too many "redirect"`) ErrTooManyExps = errors.New(`too many "exp"`) ErrSyntaxError = errors.New(`wrong syntax`) ErrEmptyDomain = errors.New("empty domain") ErrNotIPv4 = errors.New("address isn't ipv4") ErrNotIPv6 = errors.New("address isn't ipv6") ErrLoopDetected = errors.New("infinite recursion detected") ErrUnreliableResult = errors.New("result is unreliable with IgnoreMatches option enabled") ErrTooManyErrors = errors.New("too many errors") )
Errors could be used for root couse analysis
Functions ¶
func IsKnownMechanism ¶ added in v2.1.0
func NewMiekgDNSResolver ¶
func NewMiekgDNSResolver(addr string, opts ...MiekgDNSResolverOption) (*miekgDNSResolver, error)
NewMiekgDNSResolver returns new instance of Resolver with default dns.Client
func NewPTRAddress ¶ added in v2.0.2
func NormalizeFQDN ¶
NormalizeFQDN appends a root domain (a dot) to the FQDN.
Types ¶
type CacheDump ¶
type CacheDump map[interface{}]interface{}
func (CacheDump) MarshalJSON ¶
func (*CacheDump) UnmarshalJSON ¶
type DNSResolver ¶
type DNSResolver struct{}
DNSResolver implements Resolver using local DNS
func (*DNSResolver) Exists ¶
func (r *DNSResolver) Exists(name string) (bool, *ResponseExtras, error)
Exists is used for a DNS A RR lookup (even when the connection type is IPv6). If any A record is returned, this mechanism matches and returns the ttl.
func (*DNSResolver) LookupPTR ¶ added in v2.0.2
func (r *DNSResolver) LookupPTR(name string) ([]string, *ResponseExtras, error)
LookupPTR returns the DNS PTR records for the given name and the TTL.
func (*DNSResolver) LookupTXT ¶
func (r *DNSResolver) LookupTXT(name string) ([]string, *ResponseExtras, error)
LookupTXT returns the DNS TXT records for the given domain name and the TTL.
func (*DNSResolver) LookupTXTStrict ¶
func (r *DNSResolver) LookupTXTStrict(name string) ([]string, *ResponseExtras, error)
LookupTXTStrict returns DNS TXT records for the given name and the TTL however it will return ErrDNSPermerror upon NXDOMAIN (RCODE 3)
func (*DNSResolver) MatchIP ¶
func (r *DNSResolver) MatchIP(name string, matcher IPMatcherFunc) (bool, *ResponseExtras, error)
MatchIP provides an address lookup, which should be done on the name using the type of lookup (A or AAAA). Then IPMatcherFunc used to compare checked IP to the returned address(es). If any address matches, the mechanism matches and returns the TTL with it
func (*DNSResolver) MatchMX ¶
func (r *DNSResolver) MatchMX(name string, matcher IPMatcherFunc) (bool, *ResponseExtras, error)
MatchMX is similar to MatchIP but first performs an MX lookup on the name. Then it performs an address lookup on each MX name returned. Then IPMatcherFunc used to compare checked IP to the returned address(es). If any address matches, the mechanism matches and returns the TTL.
type DomainError ¶
DomainError represents a domain check error
func (*DomainError) Error ¶
func (e *DomainError) Error() string
type IPMatcherFunc ¶
IPMatcherFunc returns true if ip matches to implemented rules. If IPMatcherFunc returns any non nil error, the Resolver must stop any further processing and use the error as resulting error. name is given for information purpose only and could be totally ignored by implementation.
type LimitedResolver ¶
type LimitedResolver struct {
// contains filtered or unexported fields
}
LimitedResolver wraps a Resolver and limits number of lookups possible to do with it. All overlimited calls return ErrDNSLimitExceeded.
func (*LimitedResolver) Exists ¶
func (r *LimitedResolver) Exists(name string) (bool, *ResponseExtras, error)
Exists is used for a DNS A RR lookup (even when the connection type is IPv6). If any A record is returned, this mechanism matches and returns the ttl. Returns false and ErrDNSLimitExceeded if total number of lookups made by underlying resolver exceed the limit.
func (*LimitedResolver) LookupPTR ¶ added in v2.0.2
func (r *LimitedResolver) LookupPTR(name string) ([]string, *ResponseExtras, error)
LookupPTR returns the DNS PTR records for the given domain name and the minimum TTL
func (*LimitedResolver) LookupTXT ¶
func (r *LimitedResolver) LookupTXT(name string) ([]string, *ResponseExtras, error)
LookupTXT returns the DNS TXT records for the given domain name and the minimum TTL. Used for "exp" modifier and do not cause DNS query.
func (*LimitedResolver) LookupTXTStrict ¶
func (r *LimitedResolver) LookupTXTStrict(name string) ([]string, *ResponseExtras, error)
LookupTXTStrict returns the DNS TXT records for the given domain name and the minimum TTL. Returns nil and ErrDNSLimitExceeded if total number of lookups made by underlying resolver exceed the limit. It will also return ErrDNSPermerror upon DNS call return error NXDOMAIN (RCODE 3)
func (*LimitedResolver) MatchIP ¶
func (r *LimitedResolver) MatchIP(name string, matcher IPMatcherFunc) (bool, *ResponseExtras, error)
MatchIP provides an address lookup, which should be done on the name using the type of lookup (A or AAAA). Then IPMatcherFunc used to compare checked IP to the returned address(es). If any address matches, the mechanism matches Returns false and ErrDNSLimitExceeded if total number of lookups made by underlying resolver exceed the limit. Also return the minimum TTL in true.
func (*LimitedResolver) MatchMX ¶
func (r *LimitedResolver) MatchMX(name string, matcher IPMatcherFunc) (bool, *ResponseExtras, error)
MatchMX is similar to MatchIP but first performs an MX lookup on the name. Then it performs an address lookup on each MX name returned. Then IPMatcherFunc used to compare checked IP to the returned address(es). If any address matches, the mechanism matches.
In addition to that limit, the evaluation of each "MX" record MUST NOT result in querying more than 10 address records -- either "A" or "AAAA" resource records. If this limit is exceeded, the "mx" mechanism MUST produce a "permerror" result.
Returns false and ErrDNSLimitExceeded if total number of lookups made by underlying resolver exceed the limit. Returns the minimum TTL in true.
type Listener ¶
type Listener interface { CheckHost(ip net.IP, domain, sender string) CheckHostResult(r Result, explanation string, extras *ResponseExtras, err error) SPFRecord(s string) Directive(unused bool, qualifier, mechanism, key, value, effectiveValue string) NonMatch(qualifier, mechanism, value string, result Result, err error) Match(qualifier, mechanism, value string, result Result, explanation string, extras *ResponseExtras, err error) FirstMatch(r Result, err error) MatchingIP(qualifier, mechanism, value, fqdn string, ipn net.IPNet, host string, ip net.IP) // LookupExtras should only be called after a Directive or CheckHost call, // to ensure updates on correct directive and state stay consistent. LookupExtras(qualifier, mechanism, value, fqdn string, extras *ResponseExtras) }
type MiekgDNSResolverOption ¶
type MiekgDNSResolverOption func(r *miekgDNSResolver)
func MiekgDNSCache ¶
func MiekgDNSCache(c z.Cache) MiekgDNSResolverOption
func MiekgDNSClient ¶
func MiekgDNSClient(c *dns.Client) MiekgDNSResolverOption
func MiekgDNSMinSaneTTL ¶
func MiekgDNSMinSaneTTL(d time.Duration) MiekgDNSResolverOption
func MiekgDNSParallelism ¶
func MiekgDNSParallelism(n int) MiekgDNSResolverOption
MiekgDNSParallelism change parallelism level of matching IP and MX Anything less than 1 used as unlimited
type Option ¶
type Option func(*parser)
Option sets an optional parameter for the evaluating e-mail with regard to SPF
func ErrorsThreshold ¶
func EvaluatedOn ¶
func HeloDomain ¶
func IgnoreMatches ¶
func IgnoreMatches() Option
func PartialMacros ¶
PartialMacros triggers partial macro expansion. Currently it expands only %{d} with provided domain, if not empty. Otherwise it keeps macro body. Escaped symbols like '%%,%-,%_' are not expanded.
func ReceivingFQDN ¶
func WithListener ¶
func WithResolver ¶
type PolicyDeploymentError ¶ added in v2.1.1
type PolicyDeploymentError struct { // Err is the error that occurred during the policy lookup. Err error // Domain is the domain that was being looked up. Domain string // Policies is the list of policies that were found as part of the lookup. Policies []string }
func (*PolicyDeploymentError) Error ¶ added in v2.1.1
func (e *PolicyDeploymentError) Error() string
func (*PolicyDeploymentError) Unwrap ¶ added in v2.1.1
func (e *PolicyDeploymentError) Unwrap() error
type Resolver ¶
type Resolver interface { // LookupTXT returns the DNS TXT records for the given domain name, // along with additional response information in ResponseExtras. LookupTXT(string) ([]string, *ResponseExtras, error) // LookupTXTStrict returns DNS TXT records for the given domain name, // and returns ErrDNSPermerror upon returned NXDOMAIN (RCODE 3), // along with additional response information in ResponseExtras. LookupTXTStrict(string) ([]string, *ResponseExtras, error) // Exists is used for a DNS A RR lookup (even when the connection type is IPv6). // If any A record is returned, this mechanism matches and a bool, // along with additional response information in ResponseExtras. Exists(string) (bool, *ResponseExtras, error) // MatchIP provides an address lookup, which should be done on the name // using the type of lookup (A or AAAA). Then IPMatcherFunc is used to compare // the checked IP to the returned address(es). If any address matches, // the mechanism matches and returns the TTL, // along with additional response information in ResponseExtras. MatchIP(string, IPMatcherFunc) (bool, *ResponseExtras, error) // MatchMX is similar to MatchIP but first performs an MX lookup on the name. // Then it performs an address lookup on each MX name returned. // IPMatcherFunc is used to compare the checked IP to the returned address(es). // If any address matches, the mechanism matches and returns a bool, // along with additional response information in ResponseExtras. MatchMX(string, IPMatcherFunc) (bool, *ResponseExtras, error) // LookupPTR returns the DNS PTR records for the given address, // along with additional response information in ResponseExtras. LookupPTR(string) ([]string, *ResponseExtras, error) }
Resolver provides an abstraction for DNS layer operations.
func NewLimitedResolver ¶
NewLimitedResolver returns a resolver which will pass up to lookupLimit calls to r. In addition to that limit, the evaluation of each "MX" record will be limited to mxQueryLimit. All calls over the limit will return ErrDNSLimitExceeded. Make sure lookupLimit includes the initial SPF lookup
func NewRetryResolver ¶
func NewRetryResolver(rr []Resolver, opts ...RetryResolverOption) Resolver
NewRetryResolver implements round-robin retry with backoff delay
type ResponseExtras ¶ added in v2.1.0
type ResponseExtras struct {
// contains filtered or unexported fields
}
ResponseExtras contains additional information returned alongside DNS query results.
func NewResponseExtras ¶ added in v2.1.0
func NewResponseExtras(ttl time.Duration, void bool, cnameChain []string) *ResponseExtras
func (*ResponseExtras) CNAMEChain ¶ added in v2.1.0
func (x *ResponseExtras) CNAMEChain() []string
func (*ResponseExtras) TTL ¶ added in v2.1.0
func (x *ResponseExtras) TTL() time.Duration
func (*ResponseExtras) Void ¶ added in v2.1.0
func (x *ResponseExtras) Void() bool
type Result ¶
type Result int
Result represents result of SPF evaluation as it defined by RFC7208 https://tools.ietf.org/html/rfc7208#section-2.6
const ( // None means either (a) no syntactically valid DNS // domain name was extracted from the SMTP session that could be used // as the one to be authorized, or (b) no SPF records were retrieved // from the DNS. None Result // Neutral result means the ADMD has explicitly stated that it // is not asserting whether the IP address is authorized. Neutral // Pass result is an explicit statement that the client // is authorized to inject mail with the given identity. Pass // Fail result is an explicit statement that the client // is not authorized to use the domain in the given identity. Fail // Softfail result is a weak statement by the publishing ADMD // that the host is probably not authorized. It has not published // a stronger, more definitive policy that results in a "fail". Softfail // Temperror result means the SPF verifier encountered a transient // (generally DNS) error while performing the check. // A later retry may succeed without further DNS operator action. Temperror // Permerror result means the domain's published records could // not be correctly interpreted. // This signals an error condition that definitely requires // DNS operator intervention to be resolved. Permerror )
func CheckHost ¶
CheckHost is a main entrypoint function evaluating e-mail with regard to SPF and it utilizes DNSResolver as a resolver. As per RFC 7208 it will accept 3 parameters: <ip> - IP{4,6} address of the connected client <domain> - domain portion of the MAIL FROM or HELO identity <sender> - MAIL FROM or HELO identity All the parameters should be parsed and dereferenced from real email fields. This means domain should already be extracted from MAIL FROM field so this function can focus on the core part.
CheckHost returns result of verification, explanations as result of "exp=", raw discovered SPF policy and error as the reason for the encountered problem.
func (Result) MarshalText ¶
func (Result) String ¶
String returns string form of the result as defined by RFC7208 https://tools.ietf.org/html/rfc7208#section-2.6
func (*Result) UnmarshalText ¶
type RetryResolverOption ¶
type RetryResolverOption func(r *retryResolver)
func BackoffDelayMin ¶
func BackoffDelayMin(d time.Duration) RetryResolverOption
func BackoffFactor ¶
func BackoffFactor(f float64) RetryResolverOption
func BackoffJitter ¶
func BackoffJitter(b bool) RetryResolverOption
func BackoffTimeout ¶
func BackoffTimeout(d time.Duration) RetryResolverOption
type SpfError ¶ added in v2.1.0
type SpfError struct {
// contains filtered or unexported fields
}
SpfError represents errors created from parsing or validation, it holds reference to faulty token as well as error describing fault
func (SpfError) TokenString ¶ added in v2.1.0
type Trace ¶
type Trace struct { Result Result `json:"result"` // the result Explanation string `json:"exp,omitempty"` // supporting information for the result ClientIP net.IP `json:"clientIp,omitempty"` // the IP address of the SMTP client Identity string `json:"identity,omitempty"` // the identity that was checked Helo string `json:"helo,omitempty"` // the host name given in the HELO or EHLO command EnvelopeFrom string `json:"envelopeFrom,omitempty"` // the envelope sender mailbox Problem error `json:"problem,omitempty"` // if an error was returned, details about the error Receiver string `json:"receiver,omitempty"` // the host name of the SPF verifier Mechanism string `json:"mechanism,omitempty"` // the mechanism that matched }
Trace holds data for "Received-SPF" header field https://tools.ietf.org/html/rfc7208#section-9.1