Skip to content

Instantly share code, notes, and snippets.

@mdpuma
Last active April 25, 2024 14:01
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mdpuma/f1c347091717240276fcb0bab737f7ec to your computer and use it in GitHub Desktop.
Save mdpuma/f1c347091717240276fcb0bab737f7ec to your computer and use it in GitHub Desktop.
Integrate rspamd with cpanel
service[rspamd]=x,x,x,/etc/init.d/rspamd restart,rspamd,_rspamd
* go to whm -> exim configuration manager
* choose advanced editor
* search spamd & replace with this:
spamd_address = 127.0.0.1 11333 variant=rspamd
set smtputf8_advertise_hosts = *
* find and disable greylisting block
* find and disable acl_smtp_data:default_check_message_pre
* find section acl_smtp_data:custom_begin_spam_scan
* complete block with this:
# Remove spam headers from outside sources
warn remove_header = x-spam-subject : x-spam-status : x-spam-score : x-spam-bar : x-spam-report : x-spam-flag : x-ham-report
# add spam-score and spam-report header when told by rspamd
# also scan outgoing messages
warn spam = nobody:true
log_message = "rspam_score: $spam_score ($spam_bar) rspam_report: $spam_report"
!authenticated = *
add_header = X-Spam-Score: $spam_score ($spam_bar)
add_header = X-Spam-Report: $spam_report
add_header = X-Spam-Action: $spam_action
warn condition = ${if eq{$spam_action}{rewrite subject}}
add_header = X-Spam-Subject: ***SPAM*** $rh_subject
add_header = X-Spam-Status: Yes
defer message = Please try again later
condition = ${if eq{$spam_action}{greylist}}
defer message = Please try again later
condition = ${if eq{$spam_action}{soft reject}}
deny message = Message discarded as high-probability spam
condition = ${if eq{$spam_action}{reject}}
7. disable acl_smtp_data:default_spam_scan, acl_smtp_rcpt:default_spam_scan_check block
8. disable acl_not_smtp:outgoing_spam_scan_over_int, acl_smtp_data:no_forward_outbound_spam_over_int
9. reject mail which get score higher than 6 if they is sent via non_smtp (sendmail, php mail())
Note: this will ignore completely messages which are sent from root user.
** Find block acl_not_smtp:custom_begin_not_smtp and paste this code
warn condition = ${if eq{$sender_address_local_part}{root} {no} {yes}}
spam = nobody:true
log_message = "rspam_score: $spam_score ($spam_bar) rspam_report: $spam_report sender_address_local_part = $sender_address_local_part"
add_header = X-Spam-Score: $spam_score ($spam_bar)
add_header = X-Spam-Report: $spam_report
add_header = X-Spam-Action: $spam_action
discard message = Message discarded as high-probability spam
condition = ${if match {$spam_report} {\NFREEMAIL_ENVFROM\N} {1} {0}}
condition = ${if >= {$spam_score_int}{60}}
deny message = Message rejected as high-probability spam
condition = ${if >= {$spam_score_int}{60}}
deny message = Message rejected as high-probability spam
condition = ${if eq{$spam_action}{reject}}
accept
** disable acl_not_smtp:end_default_outgoing_notsmtp_checkall
10. deliver mail with high score of spam to /dev/null if is try to be forwarded due email forwards
*** Put these block in to begin routers block, before router boxtrapper_autowhitelist or enforce_mail_permissions:
# version with using of delivery as save to /dev/null (logs will show actual delivery to recipient email, which is not true action)
# reject_forwarded_mail_marked_as_spam:
# driver = accept
# ignore_target_hosts = 127.0.0.1
# condition = ${if eq {${lookup {$sender_address_domain} lsearch{/etc/userdomains}{$value}}}{}{true}{false}}
# condition = ${if match{$header_X-Spam-Score:}{\N\+\+\+\+\+\N}{yes}{no}}
# # condition = ${if >= {$spam_score_int}{50}}
# domains = ! +local_domains : !$primary_hostname
# transport = file_to_devnull
silent_drop_forwarded_mail_marked_as_spam:
driver = redirect
ignore_target_hosts = 127.0.0.1
condition = ${if eq {${lookup {$sender_address_domain} lsearch{/etc/userdomains}{$value}}}{}{true}{false}}
# condition = ${if match{$header_X-Spam-Score:}{\N\+\+\+\+\+\N}{yes}{no}}
condition = ${if >= {$spam_score_int}{50}}
domains = ! +local_domains : !$primary_hostname
allow_filter
user = mailnull
file_transport = file_to_devnull
data = #Exim filter\n\
save /dev/null
** Put this transport after begin transports:
file_to_devnull:
driver = appendfile
file = /dev/null
** FIND Section: PREVIRTUALUSER add paste code below
* add router which will store Spam messages in INBOX.Junk directory
* this will cause error when you will try to save settings in to WHM/cpanel exim editor
virtual_user_spam_dir:
driver = redirect
domains = !$primary_hostname
# condition = ${if match{$header_X-Spam-Score:}{\N\+\+\+\+\+\N}{yes}{no}}
condition = ${if >= {$spam_score_int}{60}}
require_files = "+/etc/valiases/$domain:+${extract{5}{::}{${lookup passwd{${lookup{$domain}lsearch{/etc/userdomains}{$value}}}{$value}}}}/mail/$domain/$local_part"
data = "$local_part+Junk@$domain"
redirect_router = virtual_user
# cat options.inc
dns {
nameserver = ["127.0.0.1"];
}
# cat redis.conf
servers = "127.0.0.1"; # Read servers (unless write_servers are unspecified)
write_servers = "127.0.0.1"; # Servers to write data
#disabled_modules = ["ratelimit"]; # List of modules that should not use redis from this section
timeout = 2s;
db = "4";
#password = "some_password";
MM_WHITELISTED_ASN {
type = "asn";
map = "${LOCAL_CONFDIR}/local.d/whitelisted_asn.map";
description = "Messages which are coming from whitelisted ASN";
score = -10;
}
MM_BLACKLISTED_IP {
type = "ip";
map = "${LOCAL_CONFDIR}/local.d/blacklisted_sourceip.map";
description = "Blacklisted ips";
score = 12;
}
MM_WHITELISTED_IP {
type = "ip";
map = "${LOCAL_CONFDIR}/local.d/whitelisted_sourceip.map";
description = "Whitelisted ips";
score = -10;
}
MM_REJECTED_BY_SUBJECT {
type = "header";
header = "Subject";
map = "${LOCAL_CONFDIR}/local.d/rejected_by_subject.map";
regexp = true;
score = 10;
symbols = ["HAS_X_PHP_SCRIPT"];
# action = "reject";
}
MM_BLACKLISTED_BY_FORGED_SENDER {
type = "from";
filter = "email:user";
map = "${LOCAL_CONFDIR}/local.d/blacklisted_by_forged_sender.map";
symbols = ["FORGED_SENDER"];
action = "reject";
}
MM_BLACKLISTED_BY_USER {
type = "user";
map = "${LOCAL_CONFDIR}/local.d/blacklisted_by_user.map";
action = "reject";
}
MM_WHITELISTED_BY_SUBJECT {
type = "header";
header = "Subject";
map = "${LOCAL_CONFDIR}/local.d/whitelisted_by_subject.map";
regexp = true;
score = -5;
# action = "reject";
}
MM_WHITELISTED_BY_USER {
type = "user";
map = "${LOCAL_CONFDIR}/local.d/whitelisted_by_user.map";
score = -5;
# action = "reject";
}
MM_WHITELISTED_BY_ENVELOPE_FROM {
type = "from";
map = "${LOCAL_CONFDIR}/local.d/whitelisted_by_envelope_from.map";
regexp = true;
filter = "email:addr";
score = -7;
}
MM_WHITELISTED_BY_FROM_HEADER {
type = "header";
header = "From";
map = "${LOCAL_CONFDIR}/local.d/whitelisted_by_from_header.map";
regexp = true;
score = -7;
}
#MM_WHITELISTED_RSPAMD_BL {
# type = "header";
# header = "To";
# map = "${LOCAL_CONFDIR}/local.d/whitelisted_by_to_header_rspamd_bl.map";
# symbols = ["RSPAMD_URIBL"];
# action = "accept";
#}
MM_BLACKLISTED_BY_FROM_HEADER {
type = "header";
header = "From";
map = "${LOCAL_CONFDIR}/local.d/blacklisted_by_from_header.map";
regexp = true;
score = 15;
# action = "reject";
}
MM_BLACKLISTED_BY_X_PHP_HEADER {
type = "from";
symbols = ["HAS_X_PHP_SCRIPT"];
action = "reject";
map = "${LOCAL_CONFDIR}/local.d/blacklisted_by_x_php_header.map";
}
MM_MAIL_DELIVERY_FAILED {
type = "header";
header = "Subject";
map = "${LOCAL_CONFDIR}/local.d/mail_delivery_failed_subject.map"
symbols = ["IS_MAIL_DELIVERY_FAILED"];
regexp = true;
}
MM_REJECT_MAIL_DELIVERY_FAILED_BY_TO_HEADER {
type = "header";
header = "To";
map = "${LOCAL_CONFDIR}/local.d/reject_by_to_header.map";
regexp = true;
action = "reject";
#score = 10;
require_symbols = "MM_MAIL_DELIVERY_FAILED";
}
# cat logging.inc
type=file
filename=/var/log/rspamd.log
# cat actions.conf
reject = 15; # Reject when reaching this score
add_header = null; # Add header when reaching this score
greylist = 4; # Apply greylisting when reaching this score (will emit `soft reject action`)
# cat worker-controller.inc
bind_socket = "IP:11334";
password = "PASSWORD HASH";
@mdpuma
Copy link
Author

mdpuma commented Mar 10, 2023

In your case, first lines will accept email with authentication on port 587, without spam checking

# do not scan messages from submission port (or maybe you want to?)
accept condition = ${if eq{$interface_port}{587}}

@thomasstr
Copy link

Hi,

Is this setup for local rspamd?
What if you want to run it as a remote service? Just change the local IP to a remote?

@mdpuma
Copy link
Author

mdpuma commented Jun 4, 2023

Hello,

rspamd may be on same server or on remote, there is just one parameter change.

spamd_address = 127.0.0.1 11333 variant=rspamd

@jatin0123
Copy link

jatin0123 commented Jun 4, 2023 via email

@mdpuma
Copy link
Author

mdpuma commented Jun 4, 2023

Did you propose to create separate gist for remote rspamd setup, where just SINGLE line of configuration is different?

spamd_address = 127.0.0.1 11333 variant=rspamd

@thomasstr
Copy link

Hello,

rspamd may be on same server or on remote, there is just one parameter change.

spamd_address = 127.0.0.1 11333 variant=rspamd

Thanks. This setup is for incoming email right?
So then you would have to create global MX-pointers and DKIM, if you want a remote setup?

@mdpuma
Copy link
Author

mdpuma commented Jun 7, 2023

This config is useful for both, incoming and outgoing, this is defined by exim acl which every incoming message has to proceed (not matter incoming or outgoing).

MX pointers and DKIM didn't have anything in common with rspamd as software for antispam.

MX pointers anyway you have to configure to point to your mailserver, but rspamd, may reside on same server (localhost) or on remote server, but it doesn't matter for MX pointer.

@jatin0123
Copy link

jatin0123 commented Jun 7, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment