https://github.com/wikimedia/operations-puppet
Tip revision: f8b741c6b549bbe4dee172a29bd06426ecae6ad4 authored by Eric Evans on 25 May 2016, 21:23:02 UTC
stub out missing 'c' instances
stub out missing 'c' instances
Tip revision: f8b741c
exim4.conf.mx.erb
# This file is managed by puppet
##########
# Macros #
##########
CONFDIR=/etc/exim4
<% if @site == "eqiad" -%>
# wiki-mail-eqiad
WIKI_INTERFACE=<; 208.80.154.91 ; 2620:0:861:3:208:80:154:91
<% elsif @site == "codfw" -%>
# wiki-mail-codfw
WIKI_INTERFACE=<; 208.80.153.46 ; 2620:0:860:2:208:80:153:46
<% end %>
OTRSQUERY=SELECT value0 FROM system_address WHERE value0='${quote_mysql:$local_part@$domain}' AND valid_id=1;
VERP_BOUNCE_LOCALPART_REGEXP = \N^wiki-\w+-\w+-\w+-[+/\w]+$\N
###############################
# Main configuration settings #
###############################
# MySQL lookups (OTRS)
hide mysql_servers = m2-master.eqiad.wmnet/otrs/exim/<%= @otrs_mysql_password %> : m2-slave.eqiad.wmnet/otrs/exim/<%= @otrs_mysql_password %>
# LDAP lookups (Office)
ldap_default_servers = ldap-corp.<%= @site %>.wikimedia.org : ldap-corp.<%= @other_site %>.wikimedia.org
LDAPPASSWORD=<%= @smtp_ldap_password %>
domainlist system_domains = @
domainlist local_domains = +system_domains : +wikimedia_domains : +legacy_mailman_domains : +verp_domains
domainlist wikimedia_domains = lsearch;CONFDIR/wikimedia_domains
domainlist verp_domains = <%= @verp_domains.join(" : ") %>
domainlist relay_domains = +wikimedia_domains
# a list of domains to always respond defer; used for emergencies or planned downtimes
domainlist defer_domains = lsearch;CONFDIR/defer_domains
# Standard lists
domainlist legacy_mailman_domains = wikimedia.org : wikipedia.org
domainlist rt_domains = rt.wikimedia.org
domainlist phab_domains = phabricator.wikimedia.org
domainlist donate_domains = donate.wikimedia.org
hostlist wikimedia_nets = <; <%= scope.lookupvar('network::constants::all_networks').join(" ; ") %>
hostlist relay_from_hosts = <; @[] ; 127.0.0.1 ; ::1 ; <%= scope.lookupvar('network::constants::external_networks').join(" ; ") %>; 10.0.0.0/8
# Administration
log_selector = +address_rewrite +all_parents +delivery_size +deliver_time +incoming_interface +incoming_port +smtp_confirmation +smtp_protocol_error +smtp_syntax_error +tls_cipher +tls_peerdn
message_logs = false
# Policy control
acl_smtp_connect = acl_check_connect
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data
helo_try_verify_hosts = *
system_filter = CONFDIR/system_filter
# Resource control
check_spool_space = 50M
smtp_reserve_hosts = <; 127.0.0.1 ; ::1 ; +wikimedia_nets
smtp_accept_queue_per_connection = 500
deliver_queue_load_max = 800.0
queue_only_load = 100.0
remote_max_parallel = 500
smtp_connect_backlog = 128
smtp_receive_timeout = 1m
smtp_accept_max = 4000
smtp_accept_max_per_host = ${if match_ip{$sender_host_address}{+wikimedia_nets}{50}{5}}
smtp_accept_reserve = 100
# Lookups
host_lookup = *
rfc1413_hosts =
# Content filtering
spamd_address = 127.0.0.1 783
# Other
never_users = root : daemon : bin
ignore_bounce_errors_after = 0h
add_environment = <; PATH=/bin:/usr/bin
keep_environment =
# TLS
tls_certificate = /etc/ssl/localcerts/mail.wikimedia.org.chained.crt
tls_privatekey = /etc/ssl/private/mail.wikimedia.org.key
tls_advertise_hosts = *
# force Gmail over IPv4 due to reports of bad spam reputation over IPv6
dns_ipv4_lookup = gmail-smtp-in.l.google.com : aspmx.l.google.com
###############################
# Access Control Lists (ACLs) #
###############################
begin acl
acl_check_rcpt:
# If there have been ~4 times as many previous RCPT rejects than
# accepts, drop the connection
drop message = Too many ($rcpt_fail_count) rejected recipients, good bye
hosts = ! +wikimedia_nets
condition = ${if >={$rcpt_fail_count}{${eval:4*($recipients_count+1)}}}
# Accept if the source is local SMTP (a pipe)
accept hosts = :
# Deny if the local part contains @, %, /, | or !, or starts with a dot
deny local_parts = ^.*[@%!/|] : ^\\.
# Accept relaying from networks we control. Note: no address verification
# is done at this point, which is good for mail submission, but may render
# recipient callout verification by affected hosts useless.
accept domains = ! +local_domains
hosts = +relay_from_hosts
control = submission/sender_retain
# Require recipient domain to be local, or a domain we relay for
require message = Relay not permitted
domains = +local_domains : +relay_domains
set acl_m_relayed = yes
# use this only for emergencies or planned downtimes
defer message = Administratively set to defer
domains = +defer_domains
# Accept mail for postmaster without further policy checking,
# for compliance with the RFCs
accept local_parts = postmaster : abuse
set acl_m2 = skip_spamd
# Verify the recipient address for local domains, or require the
# recipient domain to exist for remote domains
require verify = recipient
# If the destination domain is a domain we relay for,
# check if the local part exists at the destination,
# reject if it doesn't.
# Accept if the destination cannot be reached within 30s.
deny domains = +relay_domains
! verify = recipient/callout=10s,maxwait=30s,defer_ok
# Check whether the sender address domain exists
require verify = sender
accept
acl_check_connect:
# Deny external connections to the internal bulk mail submission interface
deny condition = ${if match_ip{$interface_address}{WIKI_INTERFACE}{true}{false}}
! hosts = +wikimedia_nets
accept
acl_check_data:
# Let's trust local senders to not send out spam
accept hosts = +wikimedia_nets
set acl_m0 = trusted relay
# Only run through SpamAssassin if requested for this domain and
# the message is not too large
accept condition = ${if >{$message_size}{400K}}
# Skip if so requested
accept condition = ${if eq{$acl_m2}{skip_spamd}}
# Add spam headers if score >= 1
warn spam = nonexistent:true
condition = ${if >{$spam_score_int}{10}{1}{0}}
set acl_m0 = $spam_score ($spam_bar)
set acl_m1 = $spam_report
# Reject spam at high scores (> 12)
deny message = This message scored $spam_score spam points.
spam = nonexistent/defer_ok
condition = ${if >{$spam_score_int}{120}{1}{0}}
accept
###########
# Routers #
###########
begin routers
# Route mail generated by MediaWiki differently
wiki_mail:
driver = dnslookup
domains = ! +local_domains
condition = ${if and{{match_ip{$interface_address}{WIKI_INTERFACE}}{eqi{$header_X-Mailer:}{MediaWiki mailer}}}}
transport = bulk_smtp
ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; 10/8 ; 172.16/12 ; 192.168/16
no_verify
# Send donate.wikimedia.org mail to Fundraising CiviCRM server
donate:
driver = manualroute
domains = +donate_domains
route_list = * barium.frack.eqiad.wmnet byname
transport = remote_smtp
# Route non-local domains (including +relay_domains) via DNS MX and A records
dnslookup:
driver = dnslookup
domains = ! +local_domains
transport = ${if eq {$acl_m_relayed}{yes}{remote_smtp}{remote_smtp_signed}}
ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; 10/8 ; 172.16/12 ; 192.168/16
cannot_route_message = Cannot route to remote domain $domain
no_more
# Route bounce emails
mw_verp_api:
driver = accept
domains = +verp_domains
condition = ${if match{$local_part}{VERP_BOUNCE_LOCALPART_REGEXP}{true}{false}}
transport = mwverpbounceprocessor
eat:
driver = redirect
domains = +local_domains
local_parts = no-reply-notifications
data = :blackhole:
# Use the system aliasfile /etc/aliases for system domains
system_aliases:
driver = redirect
domains = +system_domains
data = ${lookup{$local_part}lsearch{/etc/aliases}}
pipe_transport = address_pipe
allow_fail
allow_defer
forbid_file
# Use alias files /etc/exim4/aliases/$domain for domains like
# wikimedia.org, wikipedia.org, wiktionary.org etc.
aliases:
driver = redirect
domains = +local_domains
require_files = CONFDIR/aliases/$domain
data = ${lookup{$local_part}lsearch*{CONFDIR/aliases/$domain}}
qualify_preserve_domain
allow_fail
allow_defer
forbid_file
include_directory = CONFDIR
pipe_transport = address_pipe
# Alias old mailing list addresses to @lists.wikimedia.org
legacy_mailing_lists:
driver = redirect
domains = +legacy_mailman_domains
data = $local_part$local_part_suffix@lists.wikimedia.org
local_parts = lsearch;CONFDIR/legacy_mailing_lists
local_part_suffix = -bounces : -bounces+* : \
-confirm+* : -join : -leave : \
-owner : -request : -admin : \
-subscribe : -unsubscribe
local_part_suffix_optional
# LDAP accounts
ldap_account:
driver = manualroute
domains = wikimedia.org
condition = ${lookup ldap \
{user="cn=eximagent,ou=other,dc=corp,dc=wikimedia,dc=org" pass=LDAPPASSWORD \
ldap:///ou=people,dc=corp,dc=wikimedia,dc=org?mail?sub?(&(objectClass=inetOrgPerson)(mail=${quote_ldap:$local_part}@$domain)(x121Address=1))} \
{true}fail}
local_part_suffix = +*
local_part_suffix_optional
transport = remote_smtp
route_list = * aspmx.l.google.com
ldap_group:
driver = manualroute
domains = wikimedia.org
condition = ${lookup ldap \
{user="cn=eximagent,ou=other,dc=corp,dc=wikimedia,dc=org" pass=LDAPPASSWORD \
ldap:///ou=groups,dc=corp,dc=wikimedia,dc=org?businessCategory?sub?(businessCategory=${quote_ldap:$local_part}@$domain)} \
{true}fail}
local_part_suffix = +*
local_part_suffix_optional
transport = remote_smtp
route_list = * aspmx.l.google.com
ldap_alias:
driver = redirect
domains = wikimedia.org
data = ${lookup ldap \
{user="cn=eximagent,ou=other,dc=corp,dc=wikimedia,dc=org" pass=LDAPPASSWORD \
ldap:///ou=people,dc=corp,dc=wikimedia,dc=org?mail?sub?(&(objectClass=inetOrgPerson)(initials=${quote_ldap:$local_part}@$domain)(x121Address=1))} \
{$value}fail}
# send phabricator.wm.org emails to Phabricator
phabricator:
driver = manualroute
domains = +phab_domains
route_list = * iridium.eqiad.wmnet byname
transport = remote_smtp
# Send RT mails to the RT server
rt:
driver = manualroute
domains = +rt_domains
route_list = * magnesium.wikimedia.org byname
transport = remote_smtp
# Query the OTRS MySQL server(s) for the existence of the queue address
# $local_part@$domain, and manually route to the OTRS server if
# successful.
otrs:
driver = manualroute
domains = +local_domains
condition = ${lookup mysql{OTRSQUERY}{true}fail}
route_list = * mendelevium.eqiad.wmnet byname
transport = remote_smtp
# Redirect postmaster@$domain if it hasn't been accepted before
postmaster:
driver = redirect
domains = +local_domains
local_parts = postmaster
data = postmaster@$primary_hostname
cannot_route_message = Address $local_part@$domain does not exist
##############
# Transports #
##############
begin transports
# Generic remote SMTP transport
remote_smtp:
driver = smtp
remote_smtp_signed:
driver = smtp
dkim_domain = wikimedia.org
dkim_selector = wikimedia
dkim_private_key = ${if exists{/etc/exim4/dkim/${dkim_domain}-${dkim_selector}.key}{/etc/exim4/dkim/${dkim_domain}-${dkim_selector}.key}{0}}
dkim_canon = relaxed
# Transport for sending out automated bulk (wiki) mail
# DKIM signed with wikimedia.org irrespective of actual sender domain
# but using a separate selector that only allows "wiki" as the local part
bulk_smtp:
driver = smtp
interface = WIKI_INTERFACE
helo_data = ${lookup dnsdb{ptr=$sending_ip_address}{$value}{wiki-mail.wikimedia.org}}
dkim_domain = wikimedia.org
dkim_selector = wiki-mail
dkim_private_key = ${if exists{/etc/exim4/dkim/${dkim_domain}-${dkim_selector}.key}{/etc/exim4/dkim/${dkim_domain}-${dkim_selector}.key}{0}}
dkim_canon = relaxed
# Generic pipe local delivery transport (for use by alias/forward files)
address_pipe:
driver = pipe
return_output
# POST VERP bounce emails to a MediaWiki 'bouncehandler' API
mwverpbounceprocessor:
driver = pipe
command = /usr/bin/curl -H 'Host: <%= @verp_post_connect_server %>' <%= @verp_bounce_post_url %> -d "action=bouncehandler" --data-urlencode "email@-" -o /dev/null
user = nobody
group = nogroup
###############
# Retry rules #
###############
begin retry
* * senders=wiki@wikimedia.org F,1h,15m; G,8h,1h,1.5
* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
#################
# Rewrite rules #
#################
begin rewrite
# Rewrite the envelope From for mails from internal servers in *.site.wmnet,
# as they are usually rejected by sender domain address verification.
*@*.eqiad.wmnet root@wikimedia.org F
*@*.codfw.wmnet root@wikimedia.org F
*@*.esams.wmnet root@wikimedia.org F
*@*.ulsfo.wmnet root@wikimedia.org F