Documentation ¶
Index ¶
- Variables
- func Cause(e error) (error, string)
- func NewMiekgDNSResolver(addr string, opts ...MiekgDNSResolverOption) (*miekgDNSResolver, error)
- func NormalizeFQDN(name string) string
- func Unwrap(e error) (*token, error, bool)
- type CacheDump
- type DNSResolver
- func (r *DNSResolver) Exists(name string) (bool, time.Duration, error)
- func (r *DNSResolver) LookupTXT(name string) ([]string, time.Duration, error)
- func (r *DNSResolver) LookupTXTStrict(name string) ([]string, time.Duration, error)
- func (r *DNSResolver) MatchIP(name string, matcher IPMatcherFunc) (bool, time.Duration, error)
- func (r *DNSResolver) MatchMX(name string, matcher IPMatcherFunc) (bool, time.Duration, error)
- type DomainError
- type IPMatcherFunc
- type LimitedResolver
- func (r *LimitedResolver) Exists(name string) (bool, time.Duration, error)
- func (r *LimitedResolver) LookupTXT(name string) ([]string, time.Duration, error)
- func (r *LimitedResolver) LookupTXTStrict(name string) ([]string, time.Duration, error)
- func (r *LimitedResolver) MatchIP(name string, matcher IPMatcherFunc) (bool, time.Duration, error)
- func (r *LimitedResolver) MatchMX(name string, matcher IPMatcherFunc) (bool, time.Duration, error)
- type Listener
- type MiekgDNSResolverOption
- type Option
- type Resolver
- type Result
- type RetryResolverOption
- type SyntaxError
- type Trace
Constants ¶
This section is empty.
Variables ¶
var ( ErrDNSTemperror = errors.New("temporary DNS error") ErrDNSPermerror = errors.New("permanent DNS error") ErrDNSLimitExceeded = errors.New("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 NewMiekgDNSResolver ¶
func NewMiekgDNSResolver(addr string, opts ...MiekgDNSResolverOption) (*miekgDNSResolver, error)
NewMiekgDNSResolver returns new instance of Resolver with default dns.Client
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 ¶
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) LookupTXT ¶
LookupTXT returns the DNS TXT records for the given domain name and the TTL.
func (*DNSResolver) LookupTXTStrict ¶
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, time.Duration, 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, time.Duration, 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 ¶
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) LookupTXT ¶
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 ¶
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, time.Duration, 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, time.Duration, 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, ttl time.Duration, err error) SPFRecord(s string) Directive(unused bool, qualifier, mechanism, value, effectiveValue string) NonMatch(qualifier, mechanism, value string, result Result, err error) Match(qualifier, mechanism, value string, result Result, explanation string, ttl time.Duration, err error) MatchingIP(qualifier, mechanism, value string, fqdn string, ipn net.IPNet, host string, ip net.IP) }
type MiekgDNSResolverOption ¶
type MiekgDNSResolverOption func(r *miekgDNSResolver)
func MiekgDNSCache ¶
func MiekgDNSCache(c gcache.Cache) MiekgDNSResolverOption
func MiekgDNSClient ¶
func MiekgDNSClient(c *dns.Client) MiekgDNSResolverOption
func MiekgDNSParallelism ¶
func MiekgDNSParallelism(n int) MiekgDNSResolverOption
MiekgDNSParallelism change parallelism level of matching IP and MX Anything less than 1 means 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 Resolver ¶
type Resolver interface { // LookupTXT returns the DNS TXT records for the given domain name and // the minimum TTL. LookupTXT(string) ([]string, time.Duration, error) // LookupTXTStrict returns DNS TXT records for the given name and the // minimum TTL, however it will return ErrDNSPermerror upon returned // NXDOMAIN (RCODE 3) LookupTXTStrict(string) ([]string, time.Duration, 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 with it. Exists(string) (bool, time.Duration, 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. MatchIP(string, IPMatcherFunc) (bool, time.Duration, 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. MatchMX(string, IPMatcherFunc) (bool, time.Duration, error) }
Resolver provides abstraction for DNS layer
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 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 SyntaxError ¶
type SyntaxError struct {
// contains filtered or unexported fields
}
SyntaxError represents parsing error, it holds reference to faulty token as well as error describing fault
func (SyntaxError) Cause ¶
func (e SyntaxError) Cause() error
func (SyntaxError) Error ¶
func (e SyntaxError) Error() string
func (SyntaxError) TokenString ¶
func (e SyntaxError) TokenString() string
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