coredns-sign

title: coredns-sign(7)

text:
# coredns-sign(7)

## NAME
sign - adds DNSSEC records to zone files.

## DESCRIPTION
The sign plugin is used to sign (see RFC 6781) zones. In this process DNSSEC resource records are added. The signatures that sign the resource records sets have an expiration date, this means the signing process must be repeated before this expiration data is reached. Otherwise the zone's data will go BAD (RFC 4035, Section 5.5). The sign plugin takes care of this.

Only NSEC is supported, sign does not support NSEC3.

Sign works in conjunction with the file and auto plugins; this plugin signs the zones files, auto and file serve the zones data.

For this plugin to work at least one Common Signing Key, (see coredns-keygen(1)) is needed. This key (or keys) will be used to sign the entire zone. Sign does not support the ZSK/KSK split, nor will it do key or algorithm rollovers - it just signs.

Sign will:

•

(Re)-sign the zone with the CSK(s) when:

–

the last time it was signed is more than a 6 days ago. Each zone will have some jitter applied to the inception date.

–

the signature only has 14 days left before expiring.

Both these dates are only checked on the SOA's signature(s).

- Create RRSIGs that have an inception of -3 hours (minus a jitter between 0 and 18 hours) and a expiration of +32 (plus a jitter between 0 and 5 days) days for every given DNSKEY.

- Add NSEC records for all names in the zone. The TTL for these is the negative cache TTL from the SOA record.

- Add or replace all apex CDS/CDNSKEY records with the ones derived from the given keys. For each key two CDS are created one with SHA1 and another with SHA256.

- Update the SOA's serial number to the Unix epoch of when the signing happens. This will overwrite any previous serial number.

There are two ways that dictate when a zone is signed. Normally every 6 days (plus jitter) it will be resigned. If for some reason we fail this check, the 14 days before expiring kicks in.

Keys are named (following BIND9): K<name>+<alg>+<id>.key and K<name>+<alg>+<id>.private. The keys must not be included in your zone; they will be added by sign. These keys can be generated with coredns-keygen or BIND9's dnssec-keygen. You don't have to adhere to this naming scheme, but then you need to name your keys explicitly, see the keys file directive.

A generated zone is written out in a file named db.<name>.signed in the directory named by the directory directive (which defaults to /var/lib/coredns).

## SYNTAX

```
sign DBFILE [ZONES...] {

    key file|directory KEY...|DIR...

    directory DIR
}
```

- DBFILE the zone database file to read and parse. If the path is relative, the path from the root plugin will be prepended to it.

- ZONES zones it should be sign for. If empty, the zones from the configuration block are used.

- key specifies the key(s) (there can be multiple) to sign the zone. If file is used the KEY's filenames are used as is. If directory is used, sign will look in DIR for K<name>+<alg>+<id> files. Any metadata in these files (Activate, Publish, etc.) is ignored. These keys must also be Key Signing Keys (KSK).

- directory specifies the DIR where CoreDNS should save zones that have been signed. If not given this defaults to /var/lib/coredns. The zones are saved under the name db.<name>.signed. If the path is relative the path from the root plugin will be prepended to it.

Keys can be generated with coredns-keygen, to create one for use in the sign plugin, use: coredns-keygen example.org or dnssec-keygen -a ECDSAP256SHA256 -f KSK example.org.

## EXAMPLES
Sign the example.org zone contained in the file db.example.org and write the result to ./db.example.org.signed to let the file plugin pick it up and serve it. The keys used are read from /etc/coredns/keys/Kexample.org.key and /etc/coredns/keys/Kexample.org.private.

```
example.org {

    file db.example.org.signed

    sign db.example.org {

        key file /etc/coredns/keys/Kexample.org

        directory .

    }
}
```

Running this leads to the following log output (note the timers in this example have been set to shorter intervals).

```
[WARNING] plugin/file: Failed to open "open /tmp/db.example.org.signed: no such file or directory": trying again in 1m0s
[INFO] plugin/sign: Signing "example.org." because open /tmp/db.example.org.signed: no such file or directory
[INFO] plugin/sign: Successfully signed zone "example.org." in "/tmp/db.example.org.signed" with key tags "59725" and 1564766865 SOA serial, elapsed 9.357933ms, next: 2019-08-02T22:27:45.270Z
[INFO] plugin/file: Successfully reloaded zone "example.org." in "/tmp/db.example.org.signed" with serial 1564766865
```

Or use a single zone file for multiple zones, note that the ZONES are repeated for both plugins. Also note this outputs multiple signed output files. Here we use the default output directory /var/lib/coredns.

```
. {

    file /var/lib/coredns/db.example.org.signed example.org

    file /var/lib/coredns/db.example.net.signed example.net

    sign db.example.org example.org example.net {

        key directory /etc/coredns/keys

    }
}
```

This is the same configuration, but the zones are put in the server block, but note that you still need to specify what file is served for what zone in the file plugin:

```
example.org example.net {

    file var/lib/coredns/db.example.org.signed example.org

    file var/lib/coredns/db.example.net.signed example.net

    sign db.example.org {

        key directory /etc/coredns/keys

    }
}
```

Be careful to fully list the origins you want to sign, if you don't:

```
example.org example.net {

    sign plugin/sign/testdata/db.example.org miek.org {

        key file /etc/coredns/keys/Kexample.org

    }
}
```

This will lead to db.example.org be signed twice, as this entire section is parsed twice because you have specified the origins example.org and example.net in the server block.

Forcibly resigning a zone can be accomplished by removing the signed zone file (CoreDNS will keep on serving it from memory), and sending SIGUSR1 to the process to make it reload and resign the zone file.

## SEE ALSO
The DNSSEC RFCs: RFC 4033, RFC 4034 and RFC 4035. And the BCP on DNSSEC, RFC 6781. Further more the manual pages coredns-keygen(1) and dnssec-keygen(8). And the file plugin's documentation.

Coredns-keygen can be found at https://github.com/coredns/coredns-utils ⟨https://github.com/coredns/coredns-utils⟩ in the coredns-keygen directory.

Other useful DNSSEC tools can be found in ldns ⟨https://nlnetlabs.nl/projects/ldns/about/⟩, e.g. ldns-key2ds to create DS records from DNSKEYs.

## BUGS
keys directory is not implemented.


coredns-template

title: coredns-template(7)

text:
# coredns-template(7)

## NAME
template - allows for dynamic responses based on the incoming query.

## DESCRIPTION
The template plugin allows you to dynamically respond to queries by just writing a (Go) template.

## SYNTAX

```
template CLASS TYPE [ZONE...] {

    match REGEX...

    answer RR

    additional RR

    authority RR

    rcode CODE

    fallthrough [ZONE...]
}
```

- CLASS the query class (usually IN or ANY).

- TYPE the query type (A, PTR, ... can be ANY to match all types).

- ZONE the zone scope(s) for this template. Defaults to the server zones.

- REGEX Go regexp ⟨https://golang.org/pkg/regexp/⟩ that are matched against the incoming question name. Specifying no regex matches everything (default: .*). First matching regex wins.

- answer|additional|authority RR A RFC 1035 ⟨https://tools.ietf.org/html/rfc1035#section-5⟩ style resource record fragment built by a Go template ⟨https://golang.org/pkg/text/template/⟩ that contains the reply.

- rcode CODE A response code (NXDOMAIN, SERVFAIL, ...). The default is SUCCESS.

- fallthrough Continue with the next plugin if the zone matched but no regex matched. If specific zones are listed (for example in-addr.arpa and ip6.arpa), then only queries for those zones will be subject to fallthrough.

At least one answer or rcode directive is needed (e.g. rcode NXDOMAIN).

Also see ⟨#also-see⟩ contains an additional reading list.

## TEMPLATES
Each resource record is a full-featured Go template ⟨https://golang.org/pkg/text/template/⟩ with the following predefined data

- .Zone the matched zone string (e.g. example.).

- .Name the query name, as a string (lowercased).

- .Class the query class (usually IN).

- .Type the RR type requested (e.g. PTR).

- .Match an array of all matches. index .Match 0 refers to the whole match.

- .Group a map of the named capture groups.

- .Message the complete incoming DNS message.

- .Question the matched question section.

- .Remote client’s IP address

- .Meta a function that takes a metadata name and returns the value, if the metadata plugin is enabled. For example, .Meta "kubernetes/client-namespace"

The output of the template must be a RFC 1035 ⟨https://tools.ietf.org/html/rfc1035⟩ style resource record (commonly referred to as a "zone file").

WARNING there is a syntactical problem with Go templates and CoreDNS config files. Expressions

like {{$var}} will be interpreted as a reference to an environment variable by CoreDNS (and

Caddy) while {{ $var }} will work. See Bugs ⟨#bugs⟩ and corefile(5).

## METRICS
If monitoring is enabled (via the prometheus plugin) then the following metrics are exported:

- coredns_template_matches_total{server, regex} the total number of matched requests by regex.

- coredns_template_template_failures_total{server, regex,section,template} the number of times the Go templating failed. Regex, section and template label values can be used to map the error back to the config file.

- coredns_template_rr_failures_total{server, regex,section,template} the number of times the templated resource record was invalid and could not be parsed. Regex, section and template label values can be used to map the error back to the config file.

Both failure cases indicate a problem with the template configuration. The server label indicates the server incrementing the metric, see the metrics plugin for details.

## EXAMPLES

### RESOLVE EVERYTHING TO NXDOMAIN
The most simplistic template is

```
. {

    template ANY ANY {

      rcode NXDOMAIN

    }
}
```

1.

This template uses the default zone (. or all queries)

2.

All queries will be answered (no fallthrough)

3.

The answer is always NXDOMAIN

### RESOLVE .INVALID AS NXDOMAIN
The .invalid domain is a reserved TLD (see RFC 2606 Reserved Top Level DNS Names ⟨https://tools.ietf.org/html/rfc2606#section-2⟩) to indicate invalid domains.

```
. {

    forward . 8.8.8.8

    template ANY ANY invalid {

      rcode NXDOMAIN

      authority "invalid. 60 {{ .Class }} SOA ns.invalid. hostmaster.invalid. (1 60 60 60 60)"

    }
}
```

1.

A query to .invalid will result in NXDOMAIN (rcode)

2.

A dummy SOA record is sent to hand out a TTL of 60s for caching purposes

3.

Querying .invalid in the CH class will also cause a NXDOMAIN/SOA response

4.

The default regex is .*

### BLOCK INVALID SEARCH DOMAIN COMPLETIONS
Imagine you run example.com with a datacenter dc1.example.com. The datacenter domain is part of the DNS search domain. However something.example.com.dc1.example.com would indicate a fully qualified domain name (something.example.com) that inadvertently has the default domain or search path (dc1.example.com) added.

```
. {

    forward . 8.8.8.8

    template IN ANY example.com.dc1.example.com {

      rcode NXDOMAIN

      authority "{{ .Zone }} 60 IN SOA ns.example.com hostmaster.example.com (1 60 60 60 60)"

    }
}
```

A more verbose regex based equivalent would be

```
. {

    forward . 8.8.8.8

    template IN ANY example.com {

      match "example\.com\.(dc1\.example\.com\.)$"

      rcode NXDOMAIN

      authority "{{ index .Match 1 }} 60 IN SOA ns.{{ index .Match 1 }} hostmaster.{{ index .Match 1 }} (1 60 60 60 60)"

      fallthrough

    }
}
```

The regex-based version can do more complex matching/templating while zone-based templating is easier to read and use.

### RESOLVE A/PTR FOR .EXAMPLE

```
. {

    forward . 8.8.8.8

    # ip-a-b-c-d.example A a.b.c.d

    template IN A example {

      match (^|[.])ip-(?P<a>[0-9]*)-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$

      answer "{{ .Name }} 60 IN A {{ .Group.a }}.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}"

      fallthrough

    }

    # d.c.b.a.in-addr.arpa PTR ip-a-b-c-d.example

    template IN PTR in-addr.arpa {

      match ^(?P<d>[0-9]*)[.](?P<c>[0-9]*)[.](?P<b>[0-9]*)[.](?P<a>[0-9]*)[.]in-addr[.]arpa[.]$

      answer "{{ .Name }} 60 IN PTR ip-{{ .Group.a }}-{{ .Group.b }}-{{ .Group.c }}-{{ .Group.d }}.example."

    }
}
```

An IPv4 address consists of 4 bytes, a.b.c.d. Named groups make it less error-prone to reverse the IP address in the PTR case. Try to use named groups to explain what your regex and template are doing.

Note that the A record is actually a wildcard: any subdomain of the IP address will resolve to the IP address.

Having templates to map certain PTR/A pairs is a common pattern.

Fallthrough is needed for mixed domains where only some responses are templated.

### RESOLVE MULTIPLE IP PATTERNS

```
. {

    forward . 8.8.8.8

    template IN A example {

      match "^ip-(?P<a>10)-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]dc[.]example[.]$"

      match "^(?P<a>[0-9]*)[.](?P<b>[0-9]*)[.](?P<c>[0-9]*)[.](?P<d>[0-9]*)[.]ext[.]example[.]$"

      answer "{{ .Name }} 60 IN A {{ .Group.a}}.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}"

      fallthrough

    }
}
```

Named capture groups can be used to template one response for multiple patterns.

### RESOLVE A AND MX RECORDS FOR IP TEMPLATES IN .EXAMPLE

```
. {

    forward . 8.8.8.8

    template IN A example {

      match ^ip-10-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$

      answer "{{ .Name }} 60 IN A 10.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}"

      fallthrough

    }

    template IN MX example {

      match ^ip-10-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$

      answer "{{ .Name }} 60 IN MX 10 {{ .Name }}"

      additional "{{ .Name }} 60 IN A 10.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}"

      fallthrough

    }
}
```

### ADDING AUTHORITATIVE NAMESERVERS TO THE RESPONSE

```
. {

    forward . 8.8.8.8

    template IN A example {

      match ^ip-10-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$

      answer "{{ .Name }} 60 IN A 10.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}"

      authority  "example. 60 IN NS ns0.example."

      authority  "example. 60 IN NS ns1.example."

      additional "ns0.example. 60 IN A 203.0.113.8"

      additional "ns1.example. 60 IN A 198.51.100.8"

      fallthrough

    }

    template IN MX example {

      match ^ip-10-(?P<b>[0-9]*)-(?P<c>[0-9]*)-(?P<d>[0-9]*)[.]example[.]$

      answer "{{ .Name }} 60 IN MX 10 {{ .Name }}"

      additional "{{ .Name }} 60 IN A 10.{{ .Group.b }}.{{ .Group.c }}.{{ .Group.d }}"

      authority  "example. 60 IN NS ns0.example."

      authority  "example. 60 IN NS ns1.example."

      additional "ns0.example. 60 IN A 203.0.113.8"

      additional "ns1.example. 60 IN A 198.51.100.8"

      fallthrough

    }
}
```

## ALSO SEE

- Go regexp ⟨https://golang.org/pkg/regexp/⟩ for details about the regex implementation

- RE2 syntax reference ⟨https://github.com/google/re2/wiki/Syntax⟩ for details about the regex syntax

- RFC 1034 ⟨https://tools.ietf.org/html/rfc1034#section-3.6.1⟩ and RFC 1035 ⟨https://tools.ietf.org/html/rfc1035#section-5⟩ for the resource record format

- Go template ⟨https://golang.org/pkg/text/template/⟩ for the template language reference

## BUGS
CoreDNS supports caddyfile environment variables ⟨https://caddyserver.com/docs/caddyfile#env⟩ with notion of {$ENV_VAR}. This parser feature will break Go template variables ⟨https://golang.org/pkg/text/template/#hdr-Variables⟩ notations like{{$variable}}. The equivalent notation {{ $variable }} will work. Try to avoid Go template variables in the context of this plugin.


coredns-timeouts

title: coredns-timeouts(7)

text:
# coredns-timeouts(7)

## NAME
timeouts - allows you to configure the server read, write and idle timeouts for the TCP, TLS and DoH servers.

## DESCRIPTION
CoreDNS is configured with sensible timeouts for server connections by default. However in some cases for example where CoreDNS is serving over a slow mobile data connection the default timeouts are not optimal.

Additionally some routers hold open connections when using DNS over TLS or DNS over HTTPS. Allowing a longer idle timeout helps performance and reduces issues with such routers.

The timeouts "plugin" allows you to configure CoreDNS server read, write and idle timeouts.

## SYNTAX

```
timeouts {

    read DURATION

    write DURATION

    idle DURATION
}
```

For any timeouts that are not provided, default values are used which may vary depending on the server type. At least one timeout must be specified otherwise the entire timeouts block should be omitted.

## EXAMPLES
Start a DNS-over-TLS server that picks up incoming DNS-over-TLS queries on port 5553 and uses the nameservers defined in /etc/resolv.conf to resolve the query. This proxy path uses plain old DNS. A 10 second read timeout, 20 second write timeout and a 60 second idle timeout have been configured.

```
tls://.:5553 {

    tls cert.pem key.pem ca.pem

    timeouts {

        read 10s

        write 20s

        idle 60s

    }

    forward . /etc/resolv.conf
}
```

Start a DNS-over-HTTPS server that is similar to the previous example. Only the read timeout has been configured for 1 minute.

```
https://. {

    tls cert.pem key.pem ca.pem

    timeouts {

        read 1m

    }

    forward . /etc/resolv.conf
}
```

Start a standard TCP/UDP server on port 1053. A read and write timeout has been configured. The timeouts are only applied to the TCP side of the server.

```
.:1053 {

    timeouts {

        read 15s

                write 30s

    }

    forward . /etc/resolv.conf
}
```


coredns-tls

title: coredns-tls(7)

text:
# coredns-tls(7)

## NAME
tls - allows you to configure the server certificates for the TLS and gRPC servers.

## DESCRIPTION
CoreDNS supports queries that are encrypted using TLS (DNS over Transport Layer Security, RFC 7858) or are using gRPC (https://grpc.io/ ⟨https://grpc.io/⟩, not an IETF standard). Normally DNS traffic isn't encrypted at all (DNSSEC only signs resource records).

The tls "plugin" allows you to configure the cryptographic keys that are needed for both DNS-over-TLS and DNS-over-gRPC. If the tls plugin is omitted, then no encryption takes place.

The gRPC protobuffer is defined in pb/dns.proto. It defines the proto as a simple wrapper for the wire data of a DNS message.

## SYNTAX

```
tls CERT KEY [CA]
```

Parameter CA is optional. If not set, system CAs can be used to verify the client certificate

```
tls CERT KEY [CA] {

    client_auth nocert|request|require|verify_if_given|require_and_verify
}
```

If client_auth option is specified, it controls the client authentication policy. The option value corresponds to the ClientAuthType values of the Go tls package ⟨https://golang.org/pkg/crypto/tls/#ClientAuthType⟩: NoClientCert, RequestClientCert, RequireAnyClientCert, VerifyClientCertIfGiven, and RequireAndVerifyClientCert, respectively. The default is "nocert". Note that it makes no sense to specify parameter CA unless this option is set to verify_if_given or require_and_verify.

## EXAMPLES
Start a DNS-over-TLS server that picks up incoming DNS-over-TLS queries on port 5553 and uses the nameservers defined in /etc/resolv.conf to resolve the query. This proxy path uses plain old DNS.

```
tls://.:5553 {

    tls cert.pem key.pem ca.pem

    forward . /etc/resolv.conf
}
```

Start a DNS-over-gRPC server that is similar to the previous example, but using DNS-over-gRPC for incoming queries.

```
grpc://. {

    tls cert.pem key.pem ca.pem

    forward . /etc/resolv.conf
}
```

Only Knot DNS' kdig supports DNS-over-TLS queries, no command line client supports gRPC making debugging these transports harder than it should be.

## SEE ALSO
RFC 7858 and https://grpc.io ⟨https://grpc.io⟩.


coredns-trace

title: coredns-trace(7)

text:
# coredns-trace(7)

## NAME
trace - enables OpenTracing-based tracing of DNS requests as they go through the plugin chain.

## DESCRIPTION
With trace you enable OpenTracing of how a request flows through CoreDNS. Enable the debug plugin to get logs from the trace plugin.

## SYNTAX
The simplest form is just:

```
trace [ENDPOINT-TYPE] [ENDPOINT]
```

- ENDPOINT-TYPE is the type of tracing destination. Currently only zipkin and datadog are supported. Defaults to zipkin.

- ENDPOINT is the tracing destination, and defaults to localhost:9411. For Zipkin, if ENDPOINT does not begin with http, then it will be transformed to http://ENDPOINT/api/v1/spans.

With this form, all queries will be traced.

Additional features can be enabled with this syntax:

```
trace [ENDPOINT-TYPE] [ENDPOINT] {

    every AMOUNT

    service NAME

    client_server

    datadog_analytics_rate RATE
}
```

- every AMOUNT will only trace one query of each AMOUNT queries. For example, to trace 1 in every 100 queries, use AMOUNT of 100. The default is 1.

- service NAME allows you to specify the service name reported to the tracing server. Default is coredns.

- client_server will enable the ClientServerSameSpan OpenTracing feature.

- datadog_analytics_rate RATE will enable trace analytics ⟨https://docs.datadoghq.com/tracing/app_analytics⟩ on the traces sent from 0 to 1, 1 being every trace sent will be analyzed. This is a datadog only feature (ENDPOINT-TYPE needs to be datadog)

## ZIPKIN
You can run Zipkin on a Docker host like this:

```
docker run -d -p 9411:9411 openzipkin/zipkin
```

Note the zipkin provider does not support the v1 API since coredns 1.7.1.

## EXAMPLES
Use an alternative Zipkin address:

```
trace tracinghost:9253
```

or

```
. {

    trace zipkin tracinghost:9253
}
```

If for some reason you are using an API reverse proxy or something and need to remap the standard Zipkin URL you can do something like:

```
trace http://tracinghost:9411/zipkin/api/v1/spans
```

Using DataDog:

```
trace datadog localhost:8126
```

Trace one query every 10000 queries, rename the service, and enable same span:

```
trace tracinghost:9411 {

    every 10000

    service dnsproxy

    client_server
}
```

## SEE ALSO
See the debug plugin for more information about debug logging.


coredns-transfer

title: coredns-transfer(7)

text:
# coredns-transfer(7)

## NAME
transfer - perform (outgoing) zone transfers for other plugins.

## DESCRIPTION
This plugin answers zone transfers for authoritative plugins that implement transfer.Transferer.

transfer answers full zone transfer (AXFR) requests and incremental zone transfer (IXFR) requests with AXFR fallback if the zone has changed.

When a plugin wants to notify it's secondaries it will call back into the transfer plugin.

The following plugins implement zone transfers using this plugin: file, auto, secondary, and kubernetes. See transfer.go for implementation details if you are a plugin author that wants to use this plugin.

## SYNTAX

```
transfer [ZONE...] {

  to ADDRESS...
}
```

- ZONE The zones transfer will answer zone transfer requests for. If left blank, the zones are inherited from the enclosing server block. To answer zone transfers for a given zone, there must be another plugin in the same server block that serves the same zone, and implements transfer.Transferer.

- to ADDRESS... The hosts transfer will transfer to. Use * to permit transfers to all addresses. ADDRESS must be denoted in CIDR notation (e.g., 127.0.0.1/32) or just as plain addresses. to may be specified multiple times.

## EXAMPLES
See the specific plugins using this plugin for examples on it's usage.


coredns-tsig

title: coredns-tsig(7)

text:
# coredns-tsig(7)

## NAME
tsig - validate TSIG requests and sign responses.

## DESCRIPTION
With tsig, you can define a set of TSIG secret keys for validating incoming TSIG requests and signing responses. It can also require TSIG for certain query types, refusing requests that do not comply.

## SYNTAX

```
tsig [ZONE...] {

  secret NAME KEY

  secrets FILE

  require [QTYPE...]
}
```

- ZONE - the zones tsig will TSIG. By default, the zones from the server block are used.

- secret NAME KEY - specifies a TSIG secret for NAME with KEY. Use this option more than once to define multiple secrets. Secrets are global to the server instance, not just for the enclosing ZONE.

- secrets FILE - same as secret, but load the secrets from a file. The file may define any number

of unique keys, each in the following named.conf format:

```
 key "example." {

     secret "X28hl0BOfAL5G0jsmJWSacrwn7YRm2f6U5brnzwWEus=";

 };
```

Each key may also specify an algorithm e.g. algorithm hmac-sha256;, but this is currently ignored by the plugin.

–

require QTYPE... - the query types that must be TSIG'd. Requests of the specified types will be REFUSED if they are not signed.require all will require requests of all types to be signed. require none will not require requests any types to be signed. Default behavior is to not require.

## EXAMPLES
Require TSIG signed transactions for transfer requests to example.zone.

```
example.zone {

  tsig {

    secret example.zone.key. NoTCJU+DMqFWywaPyxSijrDEA/eC3nK0xi3AMEZuPVk=

    require AXFR IXFR

  }

  transfer {

    to *

  }
}
```

Require TSIG signed transactions for all requests to auth.zone.

```
auth.zone {

  tsig {

    secret auth.zone.key. NoTCJU+DMqFWywaPyxSijrDEA/eC3nK0xi3AMEZuPVk=

    require all

  }

  forward . 10.1.0.2
}
```

## BUGS

### ZONE TRANSFER NOTIFIES
With the transfer plugin, zone transfer notifications from CoreDNS are not TSIG signed.

### SPECIAL CONSIDERATIONS FOR FORWARDING SERVERS (RFC 8945 5.5)
https://datatracker.ietf.org/doc/html/rfc8945#section-5.5 ⟨https://datatracker.ietf.org/doc/html/rfc8945#section-5.5⟩

CoreDNS does not implement this section as follows ...

•

RFC requirement: > If the name on the TSIG is not of a secret that the server shares with the originator, the server MUST forward the message unchanged including the TSIG.

CoreDNS behavior: If ths zone of the request matches the tsig plugin zones, then the TSIG record is always stripped. But even when the tsig plugin is not involved, the forward plugin may alter the message with compression, which would cause validation failure at the destination.

•

RFC requirement: > If the TSIG passes all checks, the forwarding server MUST, if possible, include a TSIG of its own to the destination or the next forwarder.

CoreDNS behavior: If ths zone of the request matches the tsig plugin zones, forward plugin will proxy the request upstream without TSIG.

•

RFC requirement: > If no transaction security is available to the destination and the message is a query, and if the corresponding response has the AD flag (see RFC4035) set, the forwarder MUST clear the AD flag before adding the TSIG to the response and returning the result to the system from which it received the query.

CoreDNS behavior: The AD flag is not cleared.


coredns-view

title: coredns-view(7)

text:
# coredns-view(7)

## NAME
view - defines conditions that must be met for a DNS request to be routed to the server block.

## DESCRIPTION
view defines an expression that must evaluate to true for a DNS request to be routed to the server block. This enables advanced server block routing functions such as split dns.

## SYNTAX

```
view NAME {

  expr EXPRESSION
}
```

- view NAME - The name of the view used by metrics and exported as metadata for requests that match the view's expression

- expr EXPRESSION - CoreDNS will only route incoming queries to the enclosing server block if the EXPRESSION evaluates to true. See the Expressions section for available variables and functions. If multiple instances of view are defined, all EXPRESSION must evaluate to true for CoreDNS will only route incoming queries to the enclosing server block.

For expression syntax and examples, see the Expressions and Examples sections.

## EXAMPLES
Implement CIDR based split DNS routing. This will return a different answer for test. depending on client's IP address. It returns ... * test. 3600 IN A 1.1.1.1, for queries with a source address in 127.0.0.0/24 * test. 3600 IN A 2.2.2.2, for queries with a source address in 192.168.0.0/16 * test. 3600 IN A 3.3.3.3, for all others

```
. {

  view example1 {

    expr incidr(client_ip(), '127.0.0.0/24')

  }

  hosts {

    1.1.1.1 test

  }
}
. {

  view example2 {

    expr incidr(client_ip(), '192.168.0.0/16')

  }

  hosts {

    2.2.2.2 test

  }
}
. {

  hosts {

    3.3.3.3 test

  }
}
```

Send all A and AAAA requests to 10.0.0.6, and all other requests to 10.0.0.1.

```
. {

  view example {

    expr type() in ['A', 'AAAA']

  }

  forward . 10.0.0.6
}
. {

  forward . 10.0.0.1
}
```

Send all requests for abc.*.example.com (where * can be any number of labels), to 10.0.0.2, and all other requests to 10.0.0.1. Note that the regex pattern is enclosed in single quotes, and backslashes are escaped with backslashes.

```
. {

  view example {

    expr name() matches '^abc\\..*\\.example\\.com\\.$'

  }

  forward . 10.0.0.2
}
. {

  forward . 10.0.0.1
}
```

## EXPRESSIONS
To evaluate expressions, view uses the antonmedv/expr package (https://github.com/antonmedv/expr ⟨https://github.com/antonmedv/expr⟩). For example, an expression could look like: (type() == 'A' && name() == 'example.com') || client_ip() == '1.2.3.4'.

All expressions should be written to evaluate to a boolean value.

See https://github.com/antonmedv/expr/blob/master/docs/Language-Definition.md ⟨https://github.com/antonmedv/expr/blob/master/docs/Language-Definition.md⟩ as a detailed reference for valid syntax.

### AVAILABLE EXPRESSION FUNCTIONS
In the context of the view plugin, expressions can reference DNS query information by using utility functions defined below.

### DNS QUERY FUNCTIONS

- bufsize() int: the EDNS0 buffer size advertised in the query

- class() string: class of the request (IN, CH, ...)

- client_ip() string: client's IP address, for IPv6 addresses these are enclosed in brackets: [::1]

- do() bool: the EDNS0 DO (DNSSEC OK) bit set in the query

- id() int: query ID

- name() string: name of the request (the domain name requested)

- opcode() int: query OPCODE

- port() string: client's port

- proto() string: protocol used (tcp or udp)

- server_ip() string: server's IP address; for IPv6 addresses these are enclosed in brackets: [::1]

- server_port() string : client's port

- size() int: request size in bytes

- type() string: type of the request (A, AAAA, TXT, ...)

### UTILITY FUNCTIONS

- incidr(ip string, cidr string) bool: returns true if ip is within cidr

- metadata(label string) - returns the value for the metadata matching label

## METADATA
The view plugin will publish the following metadata, if the metadata plugin is also enabled:

•

view/name: the name of the view handling the current request


coredns-whoami

title: coredns-whoami(7)

text:
# coredns-whoami(7)

## NAME
whoami - returns your resolver's local IP address, port and transport.

## DESCRIPTION
The whoami plugin is not really that useful, but can be used for having a simple (fast) endpoint to test clients against. When whoami returns a response it will have your client's IP address in the additional section as either an A or AAAA record.

The reply always has an empty answer section. The port and transport are included in the additional section as a SRV record, transport can be "tcp" or "udp".

```
._<transport>.qname. 0 IN SRV 0 0 <port> .
```

The whoami plugin will respond to every A or AAAA query, regardless of the query name.

If CoreDNS can't find a Corefile on startup this is the default plugin that gets loaded. As such it can be used to check that CoreDNS is responding to queries. Other than that this plugin is of limited use in production.

## SYNTAX

```
whoami
```

## EXAMPLES
Start a server on the default port and load the whoami plugin.

```
example.org {

    whoami
}
```

When queried for "example.org A", CoreDNS will respond with:

```
;; QUESTION SECTION:
;example.org.   IN       A
;; ADDITIONAL SECTION:
example.org.            0       IN      A       10.240.0.1
_udp.example.org.       0       IN      SRV     0 0 40212
```

## SEE ALSO
Read the blog post ⟨https://coredns.io/2017/03/01/how-to-add-plugins-to-coredns/⟩ on how this plugin is built, or explore the source code ⟨https://github.com/coredns/coredns/blob/master/plugin/whoami/⟩.


package: corosync

title: cmap_keys(7)

text:
# cmap_keys(7)

## NAME
cmap_keys - Overview of keys stored in the Configuration Map

## OVERVIEW
There are 3 main types of keys stored in CMAP:

* Mapping of values stored in the config file.

* Runtime statistics.

* Other user created values.

In this man page, wild-cards have the usual meaning.

## ICMAP KEYS
These keys are in the icmap (default) map

internal_configuration.*

Internal configuration data. All keys in this prefix are read only. It's only useful for getting a list of loaded services.

logging.*

Values read from the configuration file. It's possible to change them at runtime. If subsystem specific configuration is needed, the key must be in the form logging.logger_subsys.SERVICE.key, where SERVICE is upper case name of the service and key is same as in the configuration file. All values are of string type.

nodelist.*

Values are read from the configuration file only (dynamic updates are not allowed). Each node element in the configuration file gets assigned its position starting from zero. So the first node from the config file has nodelist.node.0. prefix. To be a valid entry, each node must have ring0_addr key. To change the nodeid key, use a u32 data type. Local node position is stored in local_node_pos key (RO), so it's easy to find out nodeid/ring addresses of the local node directly from cmap.

runtime.blackbox.*

Trigger keys for storing fplay data. It's recommended that you use the corosync-blackbox command to change keys in this prefix.

runtime.force_gather

Set to 'yes' to force the processor to move into the GATHER state. This operation is dangerous and is not recommended.

runtime.config.*

Contains the values actually in use by the totem membership protocol. Values here are either taken from the Corosync configuration file, defaults or computed from entries in the config file. For information on individual keys please refer to the man page corosync.conf(5).

runtime.services.*

Prefix with statistics for service engines. Each service has its own service_id key in the prefix with the name runtime.services.SERVICE., where SERVICE is the lower case name of the service. Inside the service prefix is the number of messages received and sent by the corosync engine in the format runtime.services.SERVICE.EXEC_CALL.rx and runtime.services.SERVICE.EXEC_CALL.tx, where EXEC_CALL is the internal id of the service call (so for example 3 in cpg service is receive of multicast message from other nodes).

runtime.totem.members.*

Prefix containing members of the totem single ring protocol. Each member keys has format runtime.totem.members.NODEID.KEY, where key is one of: config_version Config version of the member node.

resources.process.PID.*

Prefix created by applications using SAM with CMAP integration. It contains the following keys: recovery Recovery policy of the process. Can be one of quit or restart.

poll_period Value passed in sam_initialize as a time_interval.

last_updated Last time SAM received a heartbeat from the client.

state State of the client. Can be one of failed, stopped, running and waiting for quorum.

uidgid.*

Information about users/groups which are allowed to make IPC connections to corosync. Entries loaded from configuration file are stored with uidgid.config.* prefix and are pruned on configuration file reload. Dynamic entries has uidgid.* prefix and a configuration file reload doesn't affect them.

quorum.cancel_wait_for_all

Tells votequorum to cancel waiting for all nodes at cluster startup. Can be used to unblock quorum if notes are known to be down. For pcs use only.

cfg.shutdown_timeout

Sets the timeout within which daemons that are registered for cfg callbacks must respond to a corosync_cfg_try_shutdown() request. the default is 5000 mS

config.reload_in_progress

This value will be set to 1 (or created) when a corosync.conf reload is started, and set to 0 when the reload is completed. This allows interested subsystems to do atomic reconfiguration rather than changing each key. Note that individual add/change/delete notifications will still be sent during a reload.

config.totemconfig_reload_in_progress

This key is similar to config.totemconfig_reload_in_progress but changed after the totem config trigger is processed. It is useful (mainly) for situations when nodelist.local_node_pos must be correctly reinstated before anything else.

## STATS KEYS
These keys are in the stats map. All keys in this map are read-only. Modification tracking of individual keys is supported in the stats map, but not prefixes. Add/Delete operations are supported on prefixes though so you can track for new ipc connections or knet interfaces.

stats.srp.*

Prefix containing statistics about totem. Typical key prefixes: commit_entered Number of times the processor entered COMMIT state.

commit_token_lost Number of times the processor lost token in COMMIT state.

consensus_timeouts How many times the processor timed out forming a consensus about membership.

continuous_gather How many times the processor was not able to reach consensus.

firewall_enabled_or_nic_failure Set to 1 when processor was not able to reach consensus for long time. The usual reason is a badly configured firewall or connection failure.

gather_entered Number of times the processor entered GATHER state.

gather_token_lost Number of times the processor lost token in GATHER state.

mcast_retx Number of retransmitted messages.

mcast_rx Number of received multicast messages.

mcast_tx Number of transmitted multicast messages.

memb_commit_token_rx Number of received commit tokens.

memb_commit_token_tx Number of transmitted commit tokens.

memb_join_rx Number of received join messages.

memb_join_tx Number of transmitted join messages.

memb_merge_detect_rx Number of received member merge messages.

memb_merge_detect_tx Number of transmitted member merge messages.

orf_token_rx Number of received orf tokens.

orf_token_tx Number of transmitted orf tokens.

recovery_entered Number of times the processor entered recovery.

recovery_token_lost Number of times the token was lost in recovery state.

rx_msg_dropped Number of received messages which were dropped because they were not expected (as example multicast message in commit state).

token_hold_cancel_rx Number of received token hold cancel messages.

token_hold_cancel_tx Number of transmitted token hold cancel messages.

mtt_rx_token Mean transit time of token in milliseconds. In other words, time between two consecutive token receives.

avg_token_workload Average time in milliseconds of holding time of token on the current processor.

avg_backlog_calc Average number of not yet sent messages on the current processor.

stats.knet.nodeX.linkY.*

Statistics about the network traffic to and from each node and link when using tke kronosnet transport connected Whether the link is connected or not

up_count Number of times this link has changed state to UP

down_count Number of times this link has changed state to DOWN

latency_ave / latency_max / latency_max Calculated latencies of this link. Note that if there has been no traffic on the link then latency_min will show a very large number.

latency_samples The number of samples used to calculate the latency figures, so you have some idea of their precision.

rx_data_packets / tx_data_packets The number of packets sent/received on this link

rx_data_bytes / tx_data_bytes The number of bytes sent/received on this link

rx_pmtu_packets / tx_pmtu_packets The number of packets sent/received by the PMTUd subsystem

rx_pmtu_bytes / tx_pmtu_bytes The number of bytes sent/received by the PMTUd subsystem

rx_ping_packets / tx_ping_packets The number of packets sent/received as pings

rx_ping_bytes / tx_ping_bytes The number of bytes sent/received as pings

rx_pong_packets / tx_pong_packets The number of packets sent/received as pongs

rx_pong_bytes / tx_pong_bytes The number of bytes sent/received as pongs

rx_total_packets / tx_total_packets The total number of packets sent/received. The aggregate of all of the above packet stats

rx_total_bytes / tx_total_bytes The total number of bytes sent/received. The aggregate of all of the above bytes stats

tx_data_retries / tx_pmtu_retries / tx_ping_retries / tx_pong_retries / tx_total_retries Number of times a transmit operation had to be retried due to the socket returning EAGAIN

stats.ipcs.*

There is information about total number of active connections from client programs at the time the request was made. active number of closed connections during whole runtime of corosync closed Total number of connections that have been made since corosync was started

stats.ipcs.ID.*

Each IPC connection has a unique ID. This is in the form [[serviceX:][PID:]internal_id. Typical keys in this prefix are:

proc_name process name of connected process (unavailable on some platforms)

dispatched number of dispatched messages.

invalid_request number of requests made by IPC which are invalid (calling non-existing call, ...).

name contains short name of the IPC connection (unavailable on some platforms).

overload is number of requests which were not processed because of overload.

queue_size contains the number of messages in the queue waiting for send.

recv_retries is the total number of interrupted receives.

requests contains the number of requests made by IPC.

responses is the number of responses sent to the IPC client.

send_retries contains the total number of interrupted sends.

service_id contains the ID of service which the IPC is connected to.

stats.schedmiss.<n>.*

If corosync is not scheduled after the required period of time it will log this event and also write an entry to the stats cmap under this key. There can be up to 10 entries (0..9) in here, when an 11th event happens the earliest will be removed. These events will always be in reverse order, so stats.schedmiss.0.* will always be the latest event kept and 9 the oldest. If you want to listen for notifications then you are recommended to listen for changes to stats.schedmiss.0.timestamp or stats.schedmiss.0.delay.

timestamp The time of the event in ms since the Epoch (ie time_t * 1000 but with valid milliseconds).

delay The time that corosync was paused (in ms, float value).

stats.clear.*

These are write-only keys used to clear the stats for various subsystems totem Clears the pg & srp totem stats.

knet Clears the knet stats

ipc Clears the ipc stats

schedmiss Clears the schedmiss stats

all Clears all of the above stats

## DYNAMIC CHANGE USER/GROUP PERMISSION TO USE COROSYNC IPC
Is the same as in the configuration file. eg: to add UID 500 use

\# corosync-cmapctl -s uidgid.uid.500 u8 1

GID is similar, so to add a GID use

\# corosync-cmapctl -s uidgid.gid.500 u8 1

For removal of permissions, simply delete the key

\# corosync-cmapctl -d uidgid.gid.500

## SEE ALSO
corosync_overview(7), corosync.conf(5), corosync-cmapctl(8)


title: corosync_overview(7)

summary: Corosync overview

text:
# corosync_overview(7)

## NAME
corosync_overview - Corosync overview

## OVERVIEW
The corosync project's purpose is to implement and support a production quality Revised BSD licensed implementation of a high performance low overhead high availability development toolkit.

Faults occur for various reasons:

* Application Faults

* Middleware Faults

* Operating System Faults

* Hardware Faults

The major focus of high availability in the past has been to mask hardware faults. Faults in other components of the system have gone unsolved until Corosync. Corosync is designed for applications to replicate their state to multiple processors, with the actual limit determined by factors such as CPU performance, network latency, and network bandwidth. The processors all contain a replica of the application state.

The corosync project provides a group message API called CPG. The project developers recommend CPG be used for most applications. The CPG service implements a closed group messaging model presenting extended virtual synchrony guarantees.

To manage conditions where the process executing the CPG application exchange fails, we provide the Simple Availability Manager (sam) to provide simple application restart.

## QUICKSTART
The corosync executive must be configured. In the directory conf in the source distribution are several files that must be copied to the /etc/corosync directory. If corosync is packaged by a distro, this may be complete.

The directory contains the file corosync.conf. Please read the corosync.conf(5) man page for details on the configuration options. The corosync project will work out of the box with the default configuration options, although the administrator may desire different options.

The corosync executive uses cryptographic techniques to ensure authenticity and privacy of the messages. In order for corosync to be secure and operate, a private key must be generated and shared to all processors.

First generate the key on one of the nodes:

```
unix# corosync-keygen
Corosync Cluster Engine Authentication key generator.
Gathering 2048 bits for key from /dev/urandom.
Writing corosync key to /etc/corosync/authkey.
```

After this operation, a private key will be in the file /etc/corosync/authkey. This private key must be copied to every processor in the cluster. If the private key isn't the same for every node, those nodes with nonmatching private keys will not be able to join the same configuration.

Copy the key to some security transportable storage or use ssh to transmit the key from node to node. Then install the key with the command:

unix#: install -D --group=0 --owner=0 --mode=0400 /path_to_authkey/authkey /etc/corosync/authkey

If a message "Invalid digest" appears from the corosync executive, the keys are not consistent between processors.

Finally run the corosync executive. If corosync is packaged from a distro, it may be set to start on system start. It may also be turned off by default in which case the init script for corosync must be enabled.

## USING LIBRARIES
The corosync libraries have header files which must be included in the developer's application. Once the header file is included, the developer can reference the corosync interfaces.

The corosync project recommends that distros place include files in /usr/include/corosync.

## IPv6
The corosync project supports both IPv4 and IPv6 network addresses. When using knet as the transport each link should have the same IP family, but different links can have different families (eg link 0 could be all IPv4, and link 1 all IPv6). When using UDP/UDPU the single link should use the same family on all nodes.

To configure a host for IPv6, use the ifconfig program to add interfaces: box20: ifconfig eth0 add fec0::1:a800:4ff:fe00:20/64 box30: ifconfig eth0 add fec0::1:a800:4ff:fe00:30/64

If the /64 is not specified, a route for the IPv6 network will not be configured which will cause significant problems. Make sure a route is available for IPv6 traffic.

## ARCHITECTURE
The corosync libraries are a thin IPC interface to the corosync executive. The corosync executive implements the functionality of the corosync APIs for distributed computing.

The corosync executive uses the Totem extended virtual synchrony protocol. The advantage to the end user is excellent performance characteristics and a proven protocol with excellent reliability. This protocol connects the processors in a configuration together so they may communicate.

## SECURITY
The corosync executive optionally encrypts and signs all messages sent over the network. For more details see crypto_model, crypto_hash and crypto_cipher options in the corosync.conf(5).

If membership messages can be captured by intruders, it is possible to execute a denial of service attack on the cluster. In this scenario, the cluster is likely already compromised and a DoS attack is the least of the administration's worries.

The security in corosync does not offer perfect forward secrecy because the keys are reused. It may be possible for an intruder to determine the shared key by capturing packets in an automated fashion. No such automated attack has been published as of yet. In this scenario, the cluster is likely already compromised to allow the long-term capture of transmitted data.

For security reasons, the corosync executive binary should NEVER be setuid or setgid in the filesystem.

## BUGS
None that are known.

## SEE ALSO
corosync.conf(5), corosync-keygen(8), corosync_quorumtool(8), corosync_cfgtool(8), corosync_cpgtool(8), corosync_cmaptool(8), cpg_overview(3), sam_overview(3)


maildirquota

package: courier-maildrop

title: maildirquota(7)

summary: voluntary Maildir quotas

text:
# maildirquota(7)

## NAME
maildirquota - voluntary Maildir quotas

## SYNOPSIS
maildirmake {-q} {10000000S} {./Maildir}

## DESCRIPTION
maildrop has a manual quota enforcement implementation that does use the quota facilities of the host operating system (filesystem-based quotas). This is an option that is set at configuration time, and may be disabled.

Using filesystem quotas sometimes leads to problems. After a hard quota is hit, most commands issued by mail clients fail, including some commands that poorly-written mail software may not expect to fail, and therefore be unable to gracefully handle the unexpected failure.

With manual quotas, the only operations that fail are the ones that most mail clients expect to fail, when the mailbox is full. However, filesystem-based quotas cannot be used in some situations, such as virtual mailboxes. If this experimental feature is enabled, approximate quota enforcement can be implemented by maildrop or deliverquota to whatever extent it's possible to do so. Quotas are enabled by the -q option to maildirmake. Both maildrop and deliverquota will observe any maildirmake-requested quota.

### LIMITATIONS
This quota mechanism will only work as long as maildrop (or deliverquota) are the only applications that deliver messages to the maildir, or as long as other applications implement the same quota enforcement mechanism. The quota enforcement mechanism is described separately in the README.maildirquota.html file in the source code distribution.

Quota enforcement will still work, to some extent, if there are other applications that deliver or modify messages in the maildir. However, quota enforcement may not kick in immediately when the maildir goes over quota, in fact the maildir can go over quota by a noticeable amount. But eventually, as long as maildrop or deliverquota are responsible for delivering the majority of messages, quota enforcement will kick in. Also, other sources of messages may also result in noticeable performance degradation, because quote recalculation will become noticeably more expensive.

Also keep in mind that this quota mechanism is generally useless if mail recipients have direct access to their maildirs.

Finally even under the best conditions this quota enforcement does have a small chance of a race condition where a maildir will go over quota by some amount. maildirs are designed for speed, and this quota implementation was designed to have as little additional overhead as possible, compared to regular maildirs. To enforce an exact quota you would have to use some kind of a locking facility, which will impose a drastic performance degradation on the overall maildir performance. A decision has been made to avoid locking, with the only negative side effect being a possibility of going over quota in very low probability situations.

A way to minimize the risk of going over quota is to set reasonable quotas, in relation to maximum message sizes supported by your mail server. If you set your maildir quota to five gigabytes, for example, it makes very little sense to configure your mail server to accept messages up to three gigabytes in size. Your maildir quota should be chosen so that it makes sense when compared to the maximum message size allowed by your mail server.

### FOLDERS
This quota implementation is compatible with a popular extension to maildir which defines individual mail folders within a single maildir. However, in order to create a compatible folder, you MUST use the maildirmake command that comes with maildrop, and you MUST use the -f option to maildirmake, giving the name of the folder. Do not use maildirmake and specify the directory name of the maildir folder. Quota enforcement will not work if you do that.

## SEE ALSO
maildrop(1)[1], maildirmake(1)[2], maildropfilter(5)[3], deliverquota(8)[4].

## AUTHOR
Sam Varshavchik

Author

## NOTES
1.

maildrop(1)

http://www.courier-mta.org/maildrop.html

2.

maildirmake(1)

http://www.courier-mta.org/maildirmake.html

3.

maildropfilter(5)

http://www.courier-mta.org/maildropfilter.html

4.

deliverquota(8)

http://www.courier-mta.org/deliverquota.html


maildropex

title: maildropex(7)

summary: maildrop filtering language examples

text:
# maildropex(7)

## NAME
maildropex - maildrop filtering language examples

## SYNOPSIS
$HOME/.mailfilter, $HOME/.mailfilters/*

## DESCRIPTION
If $HOME/.mailfilter exists, filtering instructions in this file will be carried out prior to delivering the message. The filtering instructions may instruct maildrop to discard the message, save the message in a different mailbox, or forward the message to another address. If $HOME/.mailfilter does not exist, or does not provide explicit delivery instructions, maildrop delivers the message to the user's system mailbox.

The files in $HOME/.mailfilters are used when maildrop is invoked in embedded mode.

## EXAMPLES
Take all mail that's sent to the 'auto' mailing list, and save it in Mail/auto. The 'auto' mailing list software adds a "Delivered-To: auto@domain.com" header to all messages:

```
if (/^Delivered-To: *auto@domain\.com$/)

    to Mail/auto
```

After the to command delivers the message, maildrop automatically stops filtering and terminates without executing the subsequent instructions in the filter file.

Take all mail from <boss@domain.com> about the current project status, save it in Mail/project, then forward a copy to John:

```
if (/^From: *boss@domain\.com/ \

    && /^Subject:.*[:wbreak:]project status[:wbreak:]/)
{

    cc "!john"

    to Mail/project
}
```

Note that it is necessary to use a backslash in order to continue the if statement on the next line.

Keep copies of the last 50 messages that you received in the maildir directory 'backup'. NOTE: 'backup' must be a maildir directory, not a mailbox. You can create a maildir using the maildirmake command.

```
cc backup
`cd backup/new && rm -f dummy \`ls -t | sed -e 1,50d\``
```

Put this at the beginning of your filter file, before any other filtering instructions. This is a good idea to have when you are learning maildrop. If you make a mistake and accidentally delete a message, you can recover it from the backup/new subdirectory.

Save messages that are at least 100 lines long (approximately) into Mail/IN.Large::

```
     if ( $LINES > 100 )

        to Mail/IN.Large
```

Send messages from the auto mailing list to the program 'archive', using a lock file to make sure that only one instance of the archive program will be running at the same time:

```
     if (/^Delivered-To: *auto@domain\.com$/)

        dotlock "auto.lock" {

               to "|archive"

        }
```

Check if the Message-ID: header in the message is identical to the same header that was recently seen. Discard the message if it is, otherwise continue to filter the message:

```
`reformail -D 8000 duplicate.cache`
if ( $RETURNCODE == 0 )

    exit
```

The reformail[1] command maintains a list of recently seen Message-IDs in the file duplicate.cache.

Note

Unlike a similar feature in the formail command, reformail[1] takes care of locking the file, so it's not necessary to implement your own locking mechanism for this option.

Here's a more complicated example. This fragment is intended to go right after the message has been filtered according to your regular rules, and just before the message should be saved in your mailbox:

```
cc $DEFAULT
xfilter "reformail -r -t"
/^To:.*/
getaddr($MATCH) =~ /^.*/;
MATCH=tolower($MATCH)
flock "vacation.lock" {

        `fgrep -iqx "$MATCH" vacation.lst 2>/dev/null || { \

                  echo "$MATCH" >>vacation.lst ; \

                  exit 1 ; \

              } `
}
if ( $RETURNCODE == 0 )

   exit
to "| ( cat - ; echo ''; cat vacation.msg) | $SENDMAIL"
```

This code maintains a list of everyone who sent you mail in the file called vacation.lst. When a message is received from anyone that is not already on the list, the address is added to the list, and the contents of the file vacation.msg are mailed back to the sender. This is intended to reply notify people that you will not be answering mail for a short period of time.

The first statement saves the original message in your regular mailbox. Then, xfilter[2] is used to generate an autoreply header to the sender. The To: header in the autoreply - which was the sender of the original message - is extracted, and the getaddr[3] function is used to strip the person's name, leaving the address only. The file vacation.lst is checked, using a lock file to guarantee atomic access and update (overkill, probably). Note that the backslashes are required.

If the address is already in the file, maildrop exits, otherwise the contents of vacation.msg are appended to the autoreply header, and mailed out.

Note

An easier to make a vacation script is with mailbot(1)[4].

Here's a version of the vacation script that uses a GDBM database file instead. The difference between this script and the previous script is that the previous script will send a vacation message to a given E-mail address only once. The following script will store the time that the vacation message was sent in the GDBM file. If it's been at least a week since the vacation message has been sent to the given address, another vacation message will be sent.

Even though a GDBM database file is used, locking is still necessary because the GDBM library does not allow more than one process to open the same database file for writing:

```
cc $DEFAULT
xfilter "reformail -r -t"
/^To:.*/
getaddr($MATCH) =~ /^.*/;
MATCH=tolower($MATCH)
flock "vacation.lock" {

    current_time=time;

    if (gdbmopen("vacation.dat", "C") == 0)

    {

       if ( (prev_time=gdbmfetch($MATCH)) ne "" && \

             $prev_time >= $current_time - 60 * 60 * 24 * 7)

       {

           exit

       }

       gdbmstore($MATCH, $current_time)

       gdbmclose

    }
}
to "| ( cat - ; echo ''; cat vacation.msg) | $SENDMAIL"
```

This script requires that maildrop must be compiled with GDBM support enabled, which is done by default if GDBM libraries are present.

After you return from vacation, you can use a simple Perl script to obtain a list of everyone who sent you mail (of course, that can also be determined by examining your mailbox).

## SEE ALSO
maildrop(1)[5], maildropfilter(7)[6], reformail(1)[1], mailbot(1)[4], egrep(1), grep(1), sendmail(8).

## AUTHOR
Sam Varshavchik

Author

## NOTES
1.

reformail

http://www.courier-mta.org/maildrop/reformail.html

2.

xfilter

http://www.courier-mta.org/maildrop/maildropfilter.html#xfilter

3.

getaddr

http://www.courier-mta.org/maildrop/maildropfilter.html#getaddr

4.

mailbot(1)

http://www.courier-mta.org/maildrop/mailbot.html

5.

maildrop(1)

http://www.courier-mta.org/maildrop/maildrop.html

6.

maildropfilter(7)

http://www.courier-mta.org/maildrop/maildropfilter.html