Articles in markdown along side with theirs metdata files.
This commit is contained in:
parent
58af75b075
commit
84bcc8a017
129
web/articles/hardening_mikrotik.md
Normal file
129
web/articles/hardening_mikrotik.md
Normal file
@ -0,0 +1,129 @@
|
||||
### Contents
|
||||
|
||||
1. [Introduction](#art-1)
|
||||
2. [Ways to harden your router](#art-2)
|
||||
3. [Password protection, SSH and address-based access restriction](#art-3)
|
||||
1. [Password](#art-3-1)
|
||||
2. [SSH](#art-3-2)
|
||||
3. [Allowed Address list](#art-3-3)
|
||||
4. [Configuring service list](#art-4)
|
||||
5. [Basic firewall](#art-5)
|
||||
1. [Input chain](#art-5-1)
|
||||
2. [Forward chain](#art-5-2)
|
||||
|
||||
### 1. Introduction {#art-1}
|
||||
|
||||
<figure class="center">
|
||||
<img src="/assets/img/articles/mikrotik_please_just_dont.jpg" title="%)" alt="Just don't!">
|
||||
<figcaption>You don't want to be like this, am I right? :)</figcaption>
|
||||
</figure>
|
||||
|
||||
I always wandered, since I ~~joined a cult~~ got mine, why almost no one can properly secure them. Looks like people just don't bother to do that, and leave it as it is barely configured, and only whine when get hacked. But, holy shit, even through `Quick Set` you get a proper secure firewall, yet there are thousands of routers sticking out with a ~~naked ass~~ acessible WebFig (I bet alongside with it Winbox comes as well, didn't check).
|
||||
|
||||
In this article I'll show you how to harden your router's security. There's nothing difficult and could be find just by learning available features. Considering the firewall, I will just copy-paste a default set of rules, yeah, that feels no good, but what can I do if many haven't done even that.
|
||||
|
||||
If you are setting up a router for the first time I strongly recommend you use a default configuration as a base. First you need to reset a configuration to clear a router. For that in Winbox go to `System->Reset Configuration` and check an option `No Default Configuration`. In teminal `> system/reset-configuration no-defaults=yes`. And then using `Quick Set` configure basic access to the Internet and a LAN. We need `No Default Configuration` because these defaults doesn't include a firewall (if I recall correctly, I did that in 2019 for the last time).
|
||||
|
||||
### 2. Ways to harden your router {#art-2}
|
||||
|
||||
Vital thing to do is to keep a firmware up to date. That's another major reason why routers becomes a part of a botnet — vulnerabilities.
|
||||
|
||||
To do it in Winbox go to `System->Packages` and click a `Check For Updates` button. Or using teminal: `> system/package/update/check-for-updates`. After a reboot you need to upgrade a RouterBOARD firmware. In Winbox go to `System->RouterBOARD` and click `Upgrade` button. After that reboot a router again, go for it in `System->Reboot`. In a CLI `> system/routerboard/upgrade`, and then `> system/reboot`.
|
||||
|
||||
First thing is setting a password for your admin account. Many other articles recommend to rename it, but I never do that, because there's no access from outside anyway. Also we restrict from what addresses we can login.
|
||||
|
||||
Second, restrict access to router's configuration by IP, and disable not used services.
|
||||
|
||||
And here comes a firewall.
|
||||
|
||||
And before we start I want to give you a vital tip that will save your time, and, maybe, money — use Safe Mode! To toggle it in Winbox click button `Safe Mode` that you can find at the top left corner. In teminal press `Ctrl-X`. And when you're done, don't forget to disable this mode to save all applied changes or they will revert. Winbox will warn you about activated Safe Mode, but teminal not. :)
|
||||
|
||||
### 3. Password protection, SSH and address-based access restriction {#art-3}
|
||||
|
||||
#### 3.1. Password {#art-3-1}
|
||||
|
||||
To change a password in Winbox go to `System->Users`, double-click on your admin account and in an edit dialogue click `Password...` button. In teminal type in `> user/set admin password=new_password`.
|
||||
|
||||
#### 3.2. SSH {#art-3-2}
|
||||
|
||||
Alas, built-in SSH doesn't support modern ciphers and we cannot use keybased authentification. Hope it will change in the future. But now we have only passwords.
|
||||
|
||||
To configure SSH go to `IP->SSH`. We need there options `Always Allow Password Login` and `Strong Crypto` to be enabled. You may change `Host Key Size` to something more secure and click `Regenerate Host Key` button. Using teminal type in `> ip/ssh/set always-allow-password-login=yes strong-crypto=yes`. In a terminal works autocompletion, just tap Tab key twice. To regenerate a key type in `> ip/ssh/regenerate-host-key` and confirm.
|
||||
|
||||
#### 3.3. Allowed Address list {#art-3-3}
|
||||
|
||||
Every user can be restricted by what addresses he allowed to login from. You may have already noticed a field `Allowed Address` when was setting a password. So, again, in Winbox go to `System->Users`, double-click your user and you will see a field `Allowed Address`, there could be multiple entries that can be added/removed using arrow buttons at the end of fields. You can type in individual IP-addresses and whole subnets in CIDR (e.g. 192.168.88.0/24) notation.
|
||||
|
||||
In teminal type in `> user/set admin address=` and type all addresses separated by a comma, e.g. `address=192.168.88.3,192.168.89.0/24`.
|
||||
|
||||
### 4. Configuring service list {#art-4}
|
||||
|
||||
There are a bunch of different ways to configure your router: Winbox, SSH, Telnet, WebFig and API. And you can access its filesystem with FTP or SFTP.
|
||||
|
||||
Good thing to do first will be disabling all not needed services. Go to `IP->Services` in Winbox and then using a button with a red cross disable them, or a blue check mark to enable it. Or in an edit dialogue click `Disable` button. In teminal type in `> ip/service/set service disabled=yes`.
|
||||
|
||||
As for me, I leave only SSH and Winbox services.
|
||||
|
||||
Okay, now let's restrict access to our services by IP. It is the same as for a user, just a field called `Available From`. In teminal: `> ip/service/set service address=192.168.88.2,192.168.89.0/24`.
|
||||
|
||||
### 5. Basic firewall {#art-5}
|
||||
|
||||
As I previously stated, default firewall we get using `Quick Set` is pretty much sufficient.
|
||||
|
||||
Go to `IP->Firewall` in Winbox or `> ip/firewall/filter` in teminal. For IPv6 sections called `IPv6` for Winbox, and `ipv6` for teminal.
|
||||
|
||||
In terminal you can switch to a needed section instead of typing it every time. To add a rule there is a command called `add`, and `remove` to remove a rule by its number. To see all rules and theirs numbers type `print` command.
|
||||
|
||||
Next I will give you set of rules for input and forward chains for IPv4 and IPv6. Those are very basic rules that allows already established connections in, allows ping our router from the Internet, and drops any other traffic that comes from anywhere else but not our LAN. Allows new connections from Internet only if there is a `dstnat` rule in a NAT table for that port.
|
||||
|
||||
#### 5.1. Input chain {#art-5-1}
|
||||
|
||||
A basic input chain for IPv4:
|
||||
|
||||
1 chain=input action=accept connection-state=established,related,untracked
|
||||
2 chain=input action=drop connection-state=invalid
|
||||
3 chain=input action=accept protocol=icmp
|
||||
4 chain=input action=drop in-interface-list=!LAN
|
||||
|
||||
Here the first rule let already allowed traffic to go in a router. The second one drops packets with invalid state. The third one allows pinging our router. And the fourth one drop all the packets that doesn't originate from interfaces listed in a LAN list.
|
||||
|
||||
And for IPv6:
|
||||
|
||||
1 chain=input action=accept connection-state=established,related,untracked
|
||||
2 chain=input action=drop connection-state=invalid
|
||||
3 chain=input action=accept protocol=icmpv6
|
||||
;;; defconf: accept UDP traceroute
|
||||
4 chain=input action=accept protocol=udp port=33434-33534
|
||||
;;; defconf: accept DHCPv6-Client prefix delegation.
|
||||
5 chain=input action=accept protocol=udp src-address=fe80::/10 dst-port=546
|
||||
6 chain=input action=drop in-interface-list=!LAN
|
||||
|
||||
As you can see pretty much the same as for IPv4 except for rules 4 and 5 that are described by their's comments above them.
|
||||
|
||||
#### 5.2. Forward chain {#art-5-2}
|
||||
|
||||
Here comes a basic forward chain for IPv4:
|
||||
|
||||
1 chain=forward action=fasttrack-connection hw-offload=yes connection-state=established,related,untracked
|
||||
2 chain=forward action=accept connection-state=established,related,untracked
|
||||
3 chain=forward action=drop connection-state=invalid
|
||||
4 chain=forward action=drop connection-state=new connection-nat-state=!dstnat in-interface-list=WAN
|
||||
|
||||
First rule makes use of fasttrack mechanism that sends traffic via short path past the CPU, so called hardware offload to a switch chip. While it drastically reduce load on a CPU, we lose ability to work with traffic allowed by this rule, like mark packets, and other things in a mangle section. But, since I don't do anything special with traffic I offload everything. If you need to do something then you can fasttrack only some traffic like the one going in and out the Internet.
|
||||
|
||||
In the last rule we deny establishing connections from outside if there is no destination NAT rule specified.
|
||||
|
||||
So, here is a forward chain for IPv6:
|
||||
|
||||
1 chain=forward action=accept connection-state=established,related,untracked
|
||||
2 chain=forward action=drop connection-state=invalid
|
||||
3 chain=forward action=drop src-address-list=bad_ipv6
|
||||
4 chain=forward action=drop dst-address-list=bad_ipv6
|
||||
5 chain=forward action=accept protocol=icmpv6
|
||||
;;; defconf: rfc4890 drop hop-limit=1
|
||||
6 chain=forward action=drop protocol=icmpv6 hop-limit=equal:1
|
||||
7 chain=forward action=drop in-interface-list=!LAN
|
||||
|
||||
As for rules 3 and 4 bad_ipv6 address list contains all reserved and special ranges that I won't provide here, these rules are here just to show off. And as you can see there is no `fasttrack-connection` rule since it is not implemented yet for IPv6.
|
||||
|
||||
If you don't use NATv6 then all you need to allow connections to your machine from outside is to create a corresponding rule: `chain=forward action=accept dst-address= dst-port= connection-state=new`. Don't think that `in-interface-list=WAN` is necessary here, we allow establishing a connection, so if we access that service from inside then just immediately leave a chain with accept action. And if you do use of NATv6 then use a last rule from IPv4 firewall instead.
|
3
web/articles/hardening_mikrotik.meta
Normal file
3
web/articles/hardening_mikrotik.meta
Normal file
@ -0,0 +1,3 @@
|
||||
Hardening Mikrotik
|
||||
20 05 2022
|
||||
How to harden security of your Mikrotik router.
|
71
web/articles/nginx_recipes_and_tips.md
Normal file
71
web/articles/nginx_recipes_and_tips.md
Normal file
@ -0,0 +1,71 @@
|
||||
### Contents
|
||||
|
||||
1. [Introduction](#art-1)
|
||||
2. [Userdir functionality like Apache's mod_userdir](#art-2)
|
||||
3. [Note on how NGiNX works with HTTP headers](#art-3)
|
||||
4. [Tell a Tor visitor of your clearnet site that you have an onion](#art-4)
|
||||
5. [Variables](#art-5)
|
||||
|
||||
### 1. Introduction {#art-1}
|
||||
|
||||
Here I'll place recipes for implementing different functionalities and notes on webserver's behaviour.
|
||||
|
||||
### 2. Userdir functionality like Apache's mod_userdir {#art-2}
|
||||
|
||||
Once I wanted to have a “tilde user directories” like `/~user/` which is more known as Apache's `mod_userdir` feature. I work with NGiNX so regular expressions is the way to do that.
|
||||
|
||||
Nothing special in my case. I only need to keep files there, so others may get them. Thing is simple, but I took some time to realise what regexp to use here back then.
|
||||
|
||||
The implementation is quite simple:
|
||||
|
||||
|
||||
location ~ ^/~(.+?)(/.*)?$ {
|
||||
alias /home/$1/pub$2;
|
||||
autoindex on;
|
||||
}
|
||||
|
||||
Of course, you can choose whatever place for user's public directories. In my case you need to give a read and execute permissions to user's home directory and to public directories inside them to others (`chmod o=rX /home/user`), which may be a security concern.
|
||||
|
||||
`autoindex on` will make an index of files that lies by URL. And, of course, you can put there an `index.html` file.
|
||||
|
||||
### 3. Note on how NGiNX works with HTTP headers {#art-3}
|
||||
|
||||
Let's say in `http` block you specified common headers like `X-Frame-Options`, `X-XSS-Protection`, and so on for all `server` directives to use. But, if you add some other header for a specific `server` or `location` block then all those headers would be dropped.
|
||||
|
||||
For now the only cure for it is to place all that headers in a separate file like `common-headers.inc` and using `include` directive to include them in all the `server` and `location` blocks where additional headers are added.
|
||||
|
||||
### 4. Tell a Tor visitor of your clearnet site that you have an onion {#art-4}
|
||||
|
||||
There is a custom HTTP header `Onion-Location` that is being recognised by Tor Browser and it will show a ".onion available" button in an address bar.
|
||||
|
||||
The code for NGiNX is this simple:
|
||||
|
||||
add_header Onion-Location http://yoursite.onion$request_uri;
|
||||
|
||||
### 5. Variables {#art-5}
|
||||
|
||||
Just wanna tell about this cool feature you can use to reduce code repetition. Alas, you can use them only in `server`, `location` and `if` blocks. If only they could be declared in a `http` block, they'd be perfect. But still, they help a lot.
|
||||
|
||||
I heavily use aliases pointing to directories within the same base directory.
|
||||
|
||||
Judging from a little testing, variables doesn't decrease performance. Or I just don't notice it.
|
||||
|
||||
Variables could only store strings. To demonstrate the usage I'll just post here a part of my config:
|
||||
|
||||
set $root /srv/http/dwelling;
|
||||
...
|
||||
location =/favicon.ico {
|
||||
alias $root/shared/static/img/favicon.ico;
|
||||
}
|
||||
...
|
||||
location /assets/ {
|
||||
alias $root/homepage/static/assets/;
|
||||
}
|
||||
|
||||
The very reason why I had to use variables is that `alias` doesn't work with relative paths. I wish `alias` could be relative to `root`, but we are forced to look for workarounds.
|
||||
|
||||
Update: Oh, I realised that you can declare variables in `http` block using `map` directive with `default` set to value you need. Funny, I've been using `map` to prevent LAN IPs from being logged all this time, heh. So, here's example:
|
||||
|
||||
map 1 $root {
|
||||
default /srv/http/dwelling;
|
||||
}
|
3
web/articles/nginx_recipes_and_tips.meta
Normal file
3
web/articles/nginx_recipes_and_tips.meta
Normal file
@ -0,0 +1,3 @@
|
||||
NGiNX's recipes & tips
|
||||
15 11 2021
|
||||
Tips and recipes for NGiNX webserver.
|
37
web/articles/rpi_root_on_external_drive.md
Normal file
37
web/articles/rpi_root_on_external_drive.md
Normal file
@ -0,0 +1,37 @@
|
||||
### Contents
|
||||
|
||||
1. [Introduction](#art-1)
|
||||
2. [Moving / to an external drive](#art-2)
|
||||
3. [cmdline.txt](#art-3)
|
||||
|
||||
### 1. Introduction {#art-1}
|
||||
|
||||
Raspberry Pi is known for how it wears off the SD cards (that's mostly because of logs). Thankfully you can move the root off the SD card to an external drive and leave there just a boot partition. I'm gonna use a ~~SystemD~~GNU/Linux distribution for that.
|
||||
|
||||
There's nothing different from a regular partitioning of the drives as you usually do when install a Linux distro. Just two things you need to do and be aware of.
|
||||
|
||||
First thing is that Raspberry Pi models up to version 3 rev B+ can boot only from a microSD card. Hopefully, that changed with release of 4th version.
|
||||
|
||||
Second thing is that you need to edit one file called [cmdline.txt](#art-3).
|
||||
|
||||
### 2. Moving / to an external drive {#art-2}
|
||||
|
||||
So you have your disk(s) partitioned and mounted. A boot partition on a microSD card should be formated to FAT32. You can do this with this command: `mkfs.vfat -F32 /dev/sdXY`.
|
||||
|
||||
Now you can unpack your distro to your disk's root partition and move files from `/boot` to a microSD card.
|
||||
|
||||
If you have a system previously installed on a microSD card, then move the files to a new root partition using `cp -a /path/to/sdcard/root/* /path/to/new/root`. `-a` stands for archive, which recursively copies everything preserving all the attributes and links.
|
||||
|
||||
Then after repartitioning of a microSD card, move content of a `/boot` directory to a new boot partition you made on a microSD card using `mv /path/to/new/root/boot/* /path/to/sdcard/new/boot`.
|
||||
|
||||
Of course, don't forget to add a boot mount to a `fstab` file: `UUID=xxx /boot vfat defaults 0 0`.
|
||||
|
||||
### cmdline.txt {#art-3}
|
||||
|
||||
So, the main part is done, now it is time to tell Raspberry where is a root partition.
|
||||
|
||||
In a `cmdline.txt` file we need to change `root=` part. Now it'll look like `root=/dev/mmcblk0p2 rw rootwait`, and we need to put our drive's root partition instead of that, e.g. `root=/dev/sda1 rw rootwait`.
|
||||
|
||||
Instead of `/dev/sdXY` you may try to use a `PARTUUID=`, but it didn't work for me, fully it would look like `root=PARTUUID=XXXX`.
|
||||
|
||||
And, `UUID` and `PARTUUID` can be gotten with `blkid` utility.
|
3
web/articles/rpi_root_on_external_drive.meta
Normal file
3
web/articles/rpi_root_on_external_drive.meta
Normal file
@ -0,0 +1,3 @@
|
||||
How to move a root from SD card to external drive on Raspberry Pi
|
||||
19 05 2022
|
||||
How to move a root partition to an ext. drive on Raspberry Pi.
|
686
web/articles/setting_up_a_mail_server.md
Normal file
686
web/articles/setting_up_a_mail_server.md
Normal file
@ -0,0 +1,686 @@
|
||||
### Contents
|
||||
|
||||
1. [Introduction](#art-1)
|
||||
2. [Installing](#art-2)
|
||||
3. [Postfix SMTP server](#art-3)
|
||||
1. [main.cf](#art-3-1)
|
||||
2. [master.cf](#art-3-2)
|
||||
3. [User aliases](#art-3-3)
|
||||
4. [Starting Postfix](#art-3-4)
|
||||
4. [Dovecot POP3/IMAP server with Sieve mail filter](#art-4)
|
||||
1. [Configuration files](#art-4-1)
|
||||
1. [dovecot.conf](#art-4-1-1)
|
||||
2. [10-auth.conf](#art-4-1-2)
|
||||
3. [10-logging.conf](#art-4-1-3)
|
||||
4. [10-mail.conf](#art-4-1-4)
|
||||
5. [10-master.conf](#art-4-1-5)
|
||||
6. [10-ssl.conf](#art-4-1-6)
|
||||
7. [15-lda.conf](#art-4-1-7)
|
||||
8. [15-mailboxes.conf](#art-4-1-8)
|
||||
9. [20-managesieve.conf](#art-4-1-9)
|
||||
10. [90-sieve.conf](#art-4-1-10)
|
||||
11. [auth-system.conf](#art-4-1-11)
|
||||
5. [SpamAssassin spam filter](#art-5)
|
||||
1. [Updating built-in rule set](#art-5-1)
|
||||
2. [Bayesian classifier training](#art-5-2)
|
||||
6. [OpenDKIM signing and verifying filter](#art-6)
|
||||
1. [opendkim.conf](#art-6-1)
|
||||
2. [Generating keys](#art-6-2)
|
||||
3. [Populating KeyTable and SigningTable](#art-6-3)
|
||||
4. [internal-hosts file](#art-6-4)
|
||||
5. [Starting OpenDKIM](#art-6-5)
|
||||
7. [OpenDMARC email policy filter](#art-7)
|
||||
8. [DNS records](#art-8)
|
||||
1. [MX and A/AAAA](#art-8-1)
|
||||
2. [PTR](#art-8-2)
|
||||
3. [SPF](#art-8-3)
|
||||
4. [DMARC](#art-8-4)
|
||||
5. [DKIM](#art-8-5)
|
||||
9. [Setting up a ClamAV antivirus](#art-9)
|
||||
10. [Greylisting with postgrey](#art-10)
|
||||
|
||||
### 1. Introduction {#art-1}
|
||||
|
||||
E-mail itself is a system consisting of several parts. A main E-mail protocol — SMTP is used for exchanging of mail between servers. For a user to manage his mail IMAP and POP3 protocols are used. Difference between IMAP and POP3 is that IMAP manages mail stored on a server, while POP3, once fetched mail, deletes it from server.
|
||||
|
||||
As SMTP server I use Postfix. For IMAP (I don't use POP3 because I need access from multiple devices) I use Dovecot. Dovecot is also being used for SASL authentication in Postfix. And Dovecot supports Sieve protocol, through its implementation called Pigeonhole, that allows users to write their own message filtering rules.
|
||||
|
||||
I decided to make use of greylisting. Even though I don't have a problem with spam after training of SpamAssassin. Luckily, it is very easy.
|
||||
|
||||
Server is configured in a simple way using PAM (real system users) with user's passwords and with mail stored in ~/Maildir.
|
||||
|
||||
But, as you know, there is a major problem called spam. And in order to withstand this problem there was mechanisms created. So that no one could impersonate you DKIM, DMARC and SPF were created. To ensure encrypted connection a MTA-STS (RFC8461) standard was made. To resist incoming spam anti-spam systems like SpamAssassin or spamd are used. Also it is good to check incoming mail for viruses, there are many antiviruses and I use one called ClamAV.
|
||||
|
||||
I have mentioned DKIM (DomainKeys Identified Mail), it is used to sign mail going out that it is indeed comes from your server, and verify incoming mail. And for that I use OpenDKIM implementation.
|
||||
|
||||
DMARC (Domain-based Message Authentication, Reporting and Conformance) is a policy that tells the server what to do if received mail failed some checks. To perform DMARC policy checks I use OpenDMARC implementation. OpenDMARC also performs SPF policy checks.
|
||||
|
||||
SPF (Sender Policy Framework) allows the server to check that an incoming mail came from an IP address set in SPF DNS record for domain it originates from.
|
||||
|
||||
Many servers will reject mail from a dynamic IP-address, so a static address is a must. But, from my experience, GMail, Yandex and Rambler will at least place my message to Junk directory. On Gmail I get to Inbox most of the time btw. There is such thing used against spam called block lists, and Spamhaus is the biggest player here. So, if a server uses such lists I get rejected at the stage of establishing a connection with no chance to get through anti-spam system.
|
||||
|
||||
If you have a static address then in Spamhaus you can submit your address for deletion.
|
||||
|
||||
Also, while not stated by RFCs, some servers will still reject your mail if your IP-address doesn't have a PTR DNS record set, and some will expect a PTR record to be a hostname of your server, like mail.example.org, or like my the.arav.top.
|
||||
|
||||
There is another problem known as not trusted top level domain, like mine .top domain. :) Because of how cheap it is, it is popular among spammers.
|
||||
|
||||
### 2. Installing {#art-2}
|
||||
|
||||
You need to install following packages: `postfix`, `dovecot`, `pigeonhole` (or could be named as `dovecot-sieve`), `clamav`, `opendkim`, `opendmarc`, `spamassassin`, and `postgrey`.
|
||||
|
||||
### 3. Postfix SMTP server {#art-3}
|
||||
|
||||
Its configuration files are in directory `/etc/postfix`. There are two configuration files we'll work with. The first one is a `main.cf` file. Then we configure services in `master.cf`. Also I'll show you how to make aliases for users.
|
||||
|
||||
#### 3.1. main.cf {#art-3-1}
|
||||
|
||||
So, you have `main.cf` opened, first we need to make changes in an existing configuration:
|
||||
|
||||
myhostname = mail.example.org
|
||||
mydomain = example.org
|
||||
myorigin = $mydomain
|
||||
|
||||
`myhostname` should be a subdomain that points to an IP of a mail server. This hostname is usually an A DNS record even if you have only one IP-address it is discuraged making it a CNAME.
|
||||
|
||||
`mydomain` is your domain. In `myorigin` we set a domain name from what sent mail appear. Yes, you can use other options as a variable to reduce copy-pasting.
|
||||
|
||||
inet_interfaces = all
|
||||
|
||||
In `inet_interfaces` we list interfaces we listen on. In this case we listen on all available interfaces.
|
||||
|
||||
mydestination = $myhostname, localhost, $mydomain, mail.$mydomain
|
||||
|
||||
`mydestination` is a list of domains our server deliver mail for.
|
||||
|
||||
local_recipient_maps = unix:passwd.byname $alias_maps
|
||||
|
||||
Here we tell Postfix where to look for names of local recipients.
|
||||
|
||||
mynetworks = localhost, 192.168.0.0/24
|
||||
|
||||
It is a list of trusted remote clients allowed to relay mail through our server.
|
||||
|
||||
alias_maps = hash:/etc/postfix/aliases
|
||||
alias_database = $alias_maps
|
||||
|
||||
For database of aliases we use `/etc/postfix/aliases` file in a special format we learn about later.
|
||||
|
||||
recipient_delimiter = +
|
||||
|
||||
A symbol used to separate username and an extension.
|
||||
|
||||
home_mailbox = Maildir/
|
||||
|
||||
Here we use a Maildir/ mailbox style when every message is stored in a separated file.
|
||||
|
||||
mailbox_transport = lmtp:unix:private/dovecot-lmtp
|
||||
|
||||
Here we tell Postfix what LMTP (Local Mail Transport Protocol) server to use.
|
||||
|
||||
inet_protocols = ipv4
|
||||
|
||||
Here we leave only IPv4 support, if you have an IPv6 address then you may want to add `ipv6`.
|
||||
|
||||
So here we are done with an existing configuration and ready to make our additions to add encryption, milters, configure SASL authentication, restrictions and make some tweaks.
|
||||
|
||||
And we start with configuring milters. Milter stands for mail filter, a special protocol originated in Sendmail SMTP server.
|
||||
|
||||
milter_default_action = accept
|
||||
milter_protocol = 6
|
||||
smtpd_milters =
|
||||
unix:/var/spool/opendmarc/opendmarc.sock
|
||||
unix:/var/spool/opendkim/opendkim.sock
|
||||
inet 192.168.0.54:7357
|
||||
non_smtpd_milters = $smtpd_milters
|
||||
|
||||
`milter_default_action` specifies default action of a milter to accept messages.
|
||||
|
||||
`milter_protocol` specifies protocol version used by milters, current is 6.
|
||||
|
||||
`smtpd_milters` is a list of milters the messages will go through. You can connect to milter with internet protocol with `inet:`, with a unix socket `unix:`. The last one with port 7357 is a ClamAV.
|
||||
|
||||
Now lets add some tweaks:
|
||||
|
||||
biff = no
|
||||
strict_rfc821_envelopes = yes
|
||||
disable_vrfy_command = yes
|
||||
smtpd_helo_required = yes
|
||||
smtpd_delay_reject = yes
|
||||
|
||||
mailbox_size_limit = 0
|
||||
message_size_limit = 52428800
|
||||
|
||||
`biff` set to no to disable local service for new mail notifications. It is a server, we don't need them here.
|
||||
|
||||
`strict_rfc821_envelopes` set to yes require addresses to be enclosed with <>.
|
||||
|
||||
Disabling VRFY command with `disable_vrfy_command` prevents some email addresses harvesting techniques.
|
||||
|
||||
`smtpd_helo_required` requires remote client to send HELO or EHLO command. This may stop some poorly written spam bots.
|
||||
|
||||
`smtpd_delay_reject` makes Postfix wait for RCPT TO command before evaluating some restrictions.
|
||||
|
||||
`mailbox_size_limit` and `message_size_limit` sets maximum size of a whole mailbox and of each email. Here I set no limit for a mailbox, and max of 50MiB for an email message.
|
||||
|
||||
And now it's time for SASL configuration:
|
||||
|
||||
smtpd_sasl_type = dovecot
|
||||
smtps_sasl_path = private/auth
|
||||
smtps_sasl_auth_enable = yes
|
||||
smtpd_sasl_security_options = noanonymous
|
||||
smtpd_sasl_local_domain = $mydomain
|
||||
broken_sasl_auth_clients = no
|
||||
|
||||
It's pretty clear. We chose dovecot as our SASL server, set path to it that lies within /var/spool directory, and then enabled it. Then we prohibit anonymous connections. Add our domain for SASL authentication, and deny access for the clients with obsolete version of AUTH command.
|
||||
|
||||
It's time for encryption, lets specify a list of high (strong) ciphers to use:
|
||||
|
||||
tls_high_cipherlist = ECDHE:DHE:kGOST:!aNULL:!eNULL:!RC4:!MD5:!3DES:!AES128:!CAMELLIA128:!ECDHE-RSA-AES256-SHA:!ECDHE-ECDSA-AES256-SHA
|
||||
|
||||
I took this ciphers set from [https://pub.nethence.com/security/ciphers](https://pub.nethence.com/security/ciphers).
|
||||
|
||||
Now lets configure encryption for outgoing connections.
|
||||
|
||||
smtp_use_tls = yes
|
||||
smtp_tls_security_level = encrypt
|
||||
smtp_tls_note_starttls_offer = yes
|
||||
smtp_tls_connection_reuse = yes
|
||||
smtp_tls_key_file = /etc/letsencrypt/live/example.org/privkey.pem
|
||||
smtp_tls_cert_file = /etc/letsencrypt/live/example.org/fullchain.pem
|
||||
smtp_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1
|
||||
smtp_tls_protocols = $smtp_tls_mandatory_protocols
|
||||
smtp_tls_mandatory_ciphers = high
|
||||
|
||||
First we enable it with a `smtp_use_tls`. Enforce use of encryption with (`smtp_tls_security_level`) set to encrypt. Noting servers of our ability to use encryption with option `smtp_tls_note_starttls_offer`. Reuse connection instead of opening the new one each time.
|
||||
|
||||
`smtp_tls_key_file` and `smtp_tls_cert_file` are paths to our TLS key and certificate.
|
||||
|
||||
In `smtp_tls_mandatory_protocols` and `smtp_tls_protocols` we disallow old vulnerable protocols to use. Leave only TLS version 1.2 and 1.3 available.
|
||||
|
||||
In `smtp_tls_mandatory_ciphers` we declare to use only good secure cyphers we previously set.
|
||||
|
||||
For incoming connections everything is the same, just a few more options added:
|
||||
|
||||
smtpd_use_tls = yes
|
||||
smtpd_tls_security_level = encrypt
|
||||
smtpd_tls_auth_only = yes
|
||||
smtpd_tls_key_file = /etc/letsencrypt/live/example.org/privkey.pem
|
||||
smtpd_tls_cert_file = /etc/letsencrypt/live/example.org/fullchain.pem
|
||||
smtpd_tls_mandatory_protocols = $smtp_tls_mandatory_protocols
|
||||
smtpd_tls_protocols = $smtpd_tls_mandatory_protocols
|
||||
smtpd_tls_mandatory_ciphers = $smtp_tls_mandatory_ciphers
|
||||
smtpd_tls_loglevel = 1
|
||||
smtpd_tls_received_header = yes
|
||||
smtpd_tls_session_cache_timeout = 3600s
|
||||
tls_random_source = dev:/dev/urandom
|
||||
|
||||
`smtpd_tls_auth_only` allows authorisation only on encrypted connections.
|
||||
|
||||
`smtpd_tls_loglevel` set to 1 to log a summary of a TLS handshake.
|
||||
|
||||
`smtpd_tls_received_header` makes Postfix include information about the protocol and cypher used to a `Received:` header.
|
||||
|
||||
`smtpd_tls_session_cache_timeout` is for how long to store session. `tls_random_source` is for setting an entropy source.
|
||||
|
||||
The final part is my "favorite". :) The restrictions! There is a set of them for each stage the message falls through. Here are the ones I configured:`smtpd_helo_restrictions`, `smtpd_relay_restrictions`, `smtpd_data_restrictions`, `smtpd_sender_restrictions`, and `smtpd_recipient_restrictions`.
|
||||
|
||||
So lets roll. This my working restrictions setup:
|
||||
|
||||
smtpd_helo_restrictions =
|
||||
reject_unknown_helo_hostname,
|
||||
reject_invalid_helo_hostname,
|
||||
reject_non_fqdn_helo_hostname
|
||||
|
||||
smtpd_data_restrictions =
|
||||
reject_multi_recipient_bounce,
|
||||
reject_unauth_pipelining
|
||||
|
||||
smtpd_sender_restrictions =
|
||||
permit_sasl_authenticated,
|
||||
reject_non_fqdn_sender,
|
||||
reject_unknown_sender_domain
|
||||
|
||||
smtpd_recipient_restrictions =
|
||||
reject_unknown_recipient_domain,
|
||||
reject_non_fqdn_recipient
|
||||
|
||||
In order to explain what every restriction does I'd have to copy-paste from `man 5 postconf`. :)
|
||||
|
||||
The first set of restrictions are for HELO or EHLO command, that we force the client to send with priorly set option `smtpd_helo_required` to yes. Here `reject_unknown_helo_hostname` rejects hostnames that doesn't have DNS A or MX records. `reject_invalid_helo_hostname` rejects malformed hostnames, and `reject_non_fqdn_helo_hostname` ensures that the hostname is a fully-qualified domain name.
|
||||
|
||||
The second one are for DATA command. And here man page is better than me at explaining it. Here is the link for [reject_multi_recipient_bounce](http://www.postfix.org/postconf.5.html#reject_multi_recipient_bounce) and [reject_unauth_pipelining](http://www.postfix.org/postconf.5.html#reject_unauth_pipelining). Or just look them up in `man 5 postconf`. All I can say is that it is better to have them than not to. :)
|
||||
|
||||
The rest is simpler, `permit_sasl_authenticated` in `smtpd_sender_restrictions` accepts the senders that were authenticated by SASL (e.g. Dovecot or Cyrus). And all the `reject_unknown_*` and `reject_non_fqdn_*` has the same meaning as for theirs *_helo_* counterparts, just used in theirs specific places.
|
||||
|
||||
#### 3.2. master.cf {#art-3-2}
|
||||
|
||||
The following services are needed: `smtp`, `submission`, `smtps`, and we add `spamassassin` service. The rest in this file left untouchable.
|
||||
|
||||
smtp inet n - n - - smtpd
|
||||
-o content_filter=spamassassin
|
||||
submission inet n - n - - smtpd
|
||||
-o syslog_name=postfix/submission
|
||||
-o smtpd_tls_security_level=encrypt
|
||||
-o smtpd_sasl_auth_enable=yes
|
||||
-o smtpd_tls_auth_only=yes
|
||||
-o milter_macro_daemon_name=ORIGINATING
|
||||
-o content_filter=spamassassin
|
||||
smtps inet n - n - - smtpd
|
||||
-o content_filter=spamassassin
|
||||
-o syslog_name=postfix/smtps
|
||||
-o smtpd_tls_wrappermode=yes
|
||||
-o smtpd_sasl_auth_enable=yes
|
||||
|
||||
spamassassin unix - n n - - pipe
|
||||
user=spamd argv=/bin/vendor_perl/spamc
|
||||
-e /sbin/sendmail -oi -f ${sender} ${recipient}
|
||||
|
||||
`smtp` is listening on port 25, and `smtps` on port 465. `submission` is listening on port 587 and is used by mail client to send mail.
|
||||
|
||||
#### 3.3. User aliases {#art-3-3}
|
||||
|
||||
User aliases are in `aliases` file. They has a form "`<alias>: <username>`", e.g. `me: arav`. Where `username` may be other alias. After editing you need to run `newaliases` program to update `aliases.db` file.
|
||||
|
||||
#### 3.4. Starting Postfix {#art-3-4}
|
||||
|
||||
To start a Postfix service on systemd-based Linux distro run `systemctl start postfix`. To make Postfix run on every boot run `systemctl enable postfix`.
|
||||
|
||||
### 4. Dovecot POP3/IMAP server with Sieve mail filter {#art-4}
|
||||
|
||||
As I stated in the Introduction I use only IMAP, since it keeps mail on a server.
|
||||
|
||||
First we need to create a `/etc/dovecot` directory and copy example configuration there, but we don't need everything. Example configuration lies in a `/usr/share/doc/dovecot/example-config` directory.
|
||||
|
||||
Copy `dovecot.conf` file and `conf.d` directory.
|
||||
|
||||
We will need `dovecot.conf` and files from a `conf.d` directory: 10-auth.conf, 10-mail.conf, 10-ssl.conf, 15-mailboxes.conf, 20-lmtp.conf, 90-sieve.conf, 10-logging.conf, 10-master.conf, 15-lda.conf, 20-managesieve.conf, auth-system.conf.ext.
|
||||
|
||||
Here I will leave a brief necessary explanation of options, since you will see theirs documentation when will be editing configs.
|
||||
|
||||
#### 4.1. Configuration files {#art-4-1}
|
||||
|
||||
##### 4.1.1. dovecot.conf {#art-4-1-1}
|
||||
|
||||
|
||||
protocols = imap lmtp sieve
|
||||
|
||||
Here we activate IMAP for access to mailbox, LMTP for local message delivery from Postfix and Sieve protocol for user-defined custom filters.
|
||||
|
||||
listen = *
|
||||
|
||||
Here we simply tell Dovecot to listen on all available interfaces.
|
||||
|
||||
base_dir = /var/run/dovecot
|
||||
|
||||
Uncomment setting to set a base directory for runtime files.
|
||||
|
||||
instance_name = dovecot
|
||||
|
||||
A new for this instance. In case you run multiple you can set a different names for them.
|
||||
|
||||
login_greeting = Dovecot ready.
|
||||
|
||||
A greeting message for the clients.
|
||||
|
||||
login_trusted_networks = 192.168.0.0/24 192.168.1.0/24
|
||||
|
||||
A list of trusted network ranges.
|
||||
|
||||
shutdown_clients = yes
|
||||
|
||||
I chose to force closing client connections on master process shutdown.
|
||||
|
||||
Here we are done with `dovecot.conf` file and let's go to `conf.d` directory.
|
||||
|
||||
##### 4.1.2. 10-auth.conf {#art-4-1-2}
|
||||
|
||||
|
||||
disable_plaintext_auth = yes
|
||||
|
||||
It disables login without encryption.
|
||||
|
||||
auth_realms = example.org
|
||||
|
||||
A list of realms for SASL authentication. Just leave here your domain.
|
||||
|
||||
auth_username_format = %Ln
|
||||
|
||||
I chose to drop domain.
|
||||
|
||||
auth_mechanisms = plain
|
||||
|
||||
I use a plain mechanism.
|
||||
|
||||
And, finally, at the bottom leave `auth-system.conf.ext` include directive.
|
||||
|
||||
##### 4.1.3. 10-logging.conf {#art-4-1-3}
|
||||
|
||||
Simply uncomment `log_path = syslog` there.
|
||||
|
||||
##### 4.1.4. 10-mail.conf {#art-4-1-4}
|
||||
|
||||
In `10-mail.conf` we set following:
|
||||
|
||||
mail_location = maildir:~/Maildir
|
||||
|
||||
We use Maildir/ scheme and store it in user's home directory.
|
||||
|
||||
Next set `mail_server_admin = admin@%d`, or whatever name you want. Here `%d` will expand to a domain.
|
||||
|
||||
##### 4.1.5. 10-master.conf {#art-4-1-5}
|
||||
|
||||
In section `service imap-login` uncomment everything in `inet_listener` sub-sections for IMAP and IMAPS.
|
||||
|
||||
If you want to use POP3 protocol, then do the same for `service pop3-login` section.
|
||||
|
||||
Go to `service lmtp` section and add following sub-section to enable LMTP service on a UNIX socket:
|
||||
|
||||
unix_listener /var/spool/postfix/private/dovecot-lmtp {
|
||||
group = postfix
|
||||
user = postfix
|
||||
mode = 0666
|
||||
}
|
||||
|
||||
Then go to `service auth` section and add following UNIX listener:
|
||||
|
||||
unix_listener /var/spool/postfix/private/auth {
|
||||
user = postfix
|
||||
mode = 0666
|
||||
}
|
||||
|
||||
##### 4.1.6. 10-ssl.conf {#art-4-1-6}
|
||||
|
||||
Set `ssl = required` to enable and enforce encryption.
|
||||
|
||||
In `ssl_cert` and `ssl_key` set paths to your TLS certificate and key.
|
||||
|
||||
Next you will see `ssl_key_password` where you type in your certificate's password if it is set.
|
||||
|
||||
And if you run your own PKI then you can specify your CA cert in `ssl_ca`.
|
||||
|
||||
Next good thing to do is to generate Diffie-Hellmann parameters file and set it in `ssl_dh` option. How to do it is written in a hel
|
||||
comment for this option.
|
||||
|
||||
Next set a cipher list `ssl_cipher_list` to a list you previously specified in Postfix's `main.cf` file.
|
||||
|
||||
And finally `ssl_prefer_server_ciphers = yes`.
|
||||
|
||||
##### 4.1.7. 15-lda.conf {#art-4-1-7}
|
||||
|
||||
Here we simply uncomment and set `mail_plugins = $mail_plugins sieve` in `protocol lda` section.
|
||||
|
||||
##### 4.1.8. 15-mailboxes.conf {#art-4-1-8}
|
||||
|
||||
Here in a namespace inbox leave Drafts, Junk, Trash, and Sent mailboxes. Additionally, for every mailbox I added `auto = subscribe` options so they will appear in a mail client.
|
||||
|
||||
##### 4.1.9. 20-managesieve.conf {#art-4-1-9}
|
||||
|
||||
Uncomment `protocols` option, `service managesieve-login`, and `service managesieve` sections.
|
||||
|
||||
Within `service managesieve-login` section uncomment fully `inet_listener sieve` sub-section. And next you can tweak `service_count`, `process_min_avail` and `vsz_limit` options to your taste.
|
||||
|
||||
##### 4.1.10. 90-sieve.conf {#art-4-1-10}
|
||||
|
||||
Here I just have `sieve_before = /var/lib/dovecot/sieve.d/` option uncommented, the rest is default.
|
||||
|
||||
##### 4.1.11. auth-system.conf.ext {#art-4-1-11}
|
||||
|
||||
Here is default except for in passdb I added `failure_show_msg=yes` in `args`.
|
||||
|
||||
|
||||
### 5. SpamAssassin spam filter {#art-5}
|
||||
|
||||
First, we'll work with a `local.cf` file to configure SpamAssassin.
|
||||
|
||||
I didn't any fancy tweaking here, didn't make any custom rules. I just changed options presented in file.
|
||||
|
||||
I left `rewrite_header` option commented since I don't want to append anything to a Subject header of spam messages.
|
||||
|
||||
Option `report_safe` I set to 2 to save spam messages as a text/plain attachment instead of modifying original message.
|
||||
|
||||
`trusted_networks` sets networks and hosts that are considered trusted, i.e. not spammers.
|
||||
|
||||
`lock_method` left to be flock, since I don't use NFS.
|
||||
|
||||
`required_score` left to be its default value of 5.0.
|
||||
|
||||
I use Bayesian classifier, so options `use_bayes` and `bayes_auto_learn` are set to 1.
|
||||
|
||||
I chose to normalise charset to UTF-8 with option `normalize_charset 1`.
|
||||
|
||||
Next we move to `*.pre` files.
|
||||
|
||||
In `init.pre` I commented out URIDNSBL plugin, since I don't use them.
|
||||
|
||||
In `v342.pre` I enabled `FromNameSpoof` and `Phishing` plugins.
|
||||
|
||||
#### 5.1. Updating built-in rule set {#art-5-1}
|
||||
|
||||
I sometimes run `sa-update` util to update built-in rules and pre-compile them with `sa-compile` util. After that restart SpamAssassin.
|
||||
|
||||
And so SpamAssassin make use of compiled rules ensure that a plugin Rule2XSBody in a `v320.pre` is uncommented.
|
||||
|
||||
#### 5.2. Bayesian classifier training {#art-5-2}
|
||||
|
||||
After you set up SpamAssassin for the first time you have to train Bayesian classifier. It will start to work after 200 messages will be examined.
|
||||
|
||||
For training use `sa-learn` utility and use `--ham` and `--spam` to mark messages as normal mail and spam. I additionaly have to specify a path to database with `--dbpath /var/lib/spamassassin/.spamassassin`, otherwise it will complain, so try first without it.
|
||||
|
||||
|
||||
### 6. OpenDKIM signing and verifying filter {#art-6}
|
||||
|
||||
On ArchLinux I got a problem that OpenDKIM is unable to write in `/run`, so I created `/var/spool/opendkim` directory for it.
|
||||
|
||||
After configuring it, you need to add DNS record with your public key, it is covered in [8.5](#art-8-5) section.
|
||||
|
||||
#### 6.1. opendkim.conf {#art-6-1}
|
||||
|
||||
Well, that's main config file:
|
||||
|
||||
KeyTable refile:/etc/opendkim/keytable
|
||||
SigningTable refile:/etc/opendkim/signingtable
|
||||
InternalHosts refile:/etc/opendkim/internal-hosts
|
||||
|
||||
Socket local:/var/spool/opendkim/opendkim.sock
|
||||
PidFile /var/spool/opendkim/opendkim.pid
|
||||
UMask 000
|
||||
UserID opendkim:opendkim
|
||||
|
||||
Mode sv
|
||||
SubDomains yes
|
||||
|
||||
Canonicalization relaxed/simple
|
||||
|
||||
Syslog yes
|
||||
SyslogSuccess yes
|
||||
LogWhy yes
|
||||
|
||||
SoftwareHeader yes
|
||||
|
||||
I myself set up a multi-domain variant just in case. So, here we have two main tables: `KeyTable` and `SigningTable`. Those files tells OpenDKIM where to find keys and what domains to sign. You may use one key for all domains or generate keys for each domain.
|
||||
|
||||
`InternalHosts` tells OpenDKIM what hosts should be signed rather than verified.
|
||||
|
||||
`Socket` tells where to listen to connections, in this case we use UNIX sockets.
|
||||
|
||||
`Mode` selects operating mode(s). In our case we have two modes: (s)igner and (v)erifier.
|
||||
|
||||
`SubDomains` set to yes tells that we allow subdomains of our domains to be signed and verified.
|
||||
|
||||
`Canonicalization` selects the canonicalization method(s) to be used with signing. We set relaxed for header and simple for body. I don't fully understand it and just use what suggested.
|
||||
|
||||
Below are logging options that tells to write in syslog.
|
||||
|
||||
With `SoftwareHeader` set to yes OpenDKIM will be always adding "DKIM-Filter" header field.
|
||||
|
||||
#### 6.2. Generating keys {#art-6-2}
|
||||
|
||||
opendkim-genkey -r -s myselector -b 2048 -d example.com
|
||||
|
||||
This command will generate a key pair stored in files "myselector.private" and "myselector.txt" for a given domain.
|
||||
|
||||
`-r` restricts the key to emails use only. `-s` is a name of selector.`-b` is the size of the key in bits. `-d` is our domain.
|
||||
|
||||
Name of a selector is usually a `mail`, but that's just what I use, you can choose whatever you want.
|
||||
|
||||
|
||||
#### 6.3. Populating KeyTable and SigningTable {#art-6-3}
|
||||
|
||||
KeyTable has following structure (a line per domain):
|
||||
|
||||
myselector._domainkey.example.com example.com:myselector:/etc/opendkim/myselector.private
|
||||
|
||||
And SigningTable this one:
|
||||
|
||||
*@example.com myselector._domainkey.example.com
|
||||
|
||||
#### 6.4. internal-hosts file {#art-6-4}
|
||||
|
||||
As stated above in this file we put hosts whose mail should be signed rather than verified. And its structure is the following:
|
||||
|
||||
127.0.0.1
|
||||
192.168.0.0/24
|
||||
|
||||
`127.0.0.1` is necessary to be there according to a manual.
|
||||
|
||||
|
||||
#### 6.5. Starting OpenDKIM {#art-6-5}
|
||||
|
||||
`systemctl start opendkim` and `systemctl enable opendkim` to start and enable OpenDKIM service to run on OS start up if you got Poetteringed just like me. :)
|
||||
|
||||
### 7. OpenDMARC email policy filter {#art-7}
|
||||
|
||||
Its configuration lies in `/etc/opendmarc/opendmarc.conf` and is fully documented. Here are the options I changed:
|
||||
|
||||
AuthservID OpenDMARC
|
||||
FailureReports true
|
||||
FailureReportsBcc admin@example.org
|
||||
FailureReportsSentBy admin@example.org
|
||||
IgnoreAuthenticatedClient yes
|
||||
RejectFailures true
|
||||
RequiredHeaders yes
|
||||
Socket unix:/var/spool/opendmarc/opendmarc.sock
|
||||
SoftwareHeader true
|
||||
SPFSelfValidate true
|
||||
Syslog true
|
||||
TrustedAuthservIDs mail.example.org,example.org
|
||||
UMask 002
|
||||
|
||||
What's in a `Socket` option should be added to Postfix's `smtpd_milters` and `non_smtpd_milters`.
|
||||
|
||||
Creating DMARC DNS record covered in [8.4](#art-8-4).
|
||||
|
||||
### 8. DNS records {#art-8}
|
||||
|
||||
#### 8.1. MX and A/AAAA {#art-8-1}
|
||||
|
||||
It's good to have a dedicated A (IPv4 address) or AAAA (IPv6 address) record for a mail server's hostname instead of a CNAME record so other servers won't need to do two DNS requests. Hostname is usually mail.example.org if there's just one server, you can call it whatever you want. Remind you that we set it in Postfix in `myhostname` option.
|
||||
|
||||
And A record looks like this:
|
||||
|
||||
mail IN 86400 A 203.0.113.4
|
||||
|
||||
Where `mail` is a hostname, 86400 is a TTL of a record in seconds.
|
||||
|
||||
Next we need to add a MX (mail exchanger) record that looks like this:
|
||||
|
||||
MX 10 mail.example.org.
|
||||
|
||||
Here 10 is a priority of a record. The lower a number the higher a priority.
|
||||
|
||||
A period at the end of the hostnames is necessary in DNS records.
|
||||
|
||||
#### 8.2. PTR {#art-8-2}
|
||||
|
||||
PTR is a reverse DNS record that stands for pointer and is used to “bind” a hostname to IP-address. Mail servers looks for this record and check so this name equals to a hostname provided in EHLO. Most servers will reject your mail if your PTR looks something like 1.2.3.4.pppoe.someisp.net or not set at all.
|
||||
|
||||
There are three ways to set this record: ask your hosting or internet-provider, or get your own Autonomous System (:^)).
|
||||
|
||||
Example of this record:
|
||||
|
||||
1 IN PTR mail.example.org.
|
||||
|
||||
#### 8.3. SPF {#art-8-3}
|
||||
|
||||
SPF stands for Sender Policy Framework and in my case it looks exactly like this:
|
||||
|
||||
v=spf1 +a +mx -all
|
||||
|
||||
So, `v` is a version of a protocol. `+a +mx` means that only servers specified in the A and MX DNS records could send email, and `-all` that no one else could do that.
|
||||
|
||||
#### 8.4. DMARC {#art-8-4}
|
||||
|
||||
DMARC stands for Domain-based Message Authentication Reporting and Conformance. And its DNS record could be like this one that I use:
|
||||
|
||||
_dmarc IN TXT "v=DMARC1; p=reject; rua=mailto:admin@example.org; ruf=mailto:admin@example.org; adkim=s; aspf=s"
|
||||
|
||||
`v` is a version of a protocol.
|
||||
|
||||
`p` is a default policy that could be set to `none`, `quarantine` and `reject`. I chose to `reject` mail that comes from «me” if there's something wrong with a origin of a message. If you could get email from subdomains then you need to set `sp` as well.
|
||||
|
||||
`rua` is an address for the reports and `ruf` is for the forensic reports. `aspf` verifies that an address in the MAIL FROM command and `From:` header matches example.org in strict (s) mode, and in relaxed (default, r) mode matches domain or its subdomains. For `adkim` is the same except in this case sender domain name should match a domain in `d=domain` in a `DKIM-Signature` header.
|
||||
|
||||
#### 8.5. DKIM {#art-8-5}
|
||||
|
||||
In 5.2 we generated a key pair for our domain and now we'll take what's inside a `myselector.txt` file and add it to our DNS.
|
||||
|
||||
DKIM DNS record looks like this:
|
||||
|
||||
myselector._domainkey IN TXT ( "v=DKIMv1; k=rsa; s=email; p=<public key goes here>"
|
||||
"<public key continues here>" )
|
||||
|
||||
Brackets are used in case a content of a record doesn't fit on one line, and it won't fit.
|
||||
|
||||
### 9. Setting up a ClamAV antivirus {#art-9}
|
||||
|
||||
All you need to make it work together with Postfix is to add `/run/clamav/milter.sock` to `smtpd_milters` and `non_smtpd_milters` options in Postfix, also make some changes in configs of ClamAV.
|
||||
|
||||
In `clamav-milter.conf` you need the following:
|
||||
|
||||
MilterSocket unix:/run/clamav/milter.sock
|
||||
ClamdSocket unix:/run/clamav/clamd.ctl
|
||||
|
||||
Also, in case you need ClamAV to add headers also in case a message is free of viruses add `AddHeader Add` or `AddHeader Replace` option. The difference between them is detaily described in config file itself.
|
||||
|
||||
Before starting ClamAV you need to update its virus definitions with `freshclam` util. Also, enable and start `clamav-freshclam` systemd service to keep definitions recent.
|
||||
|
||||
I don't know how it is in other distros, but, for whatever reason, an Arch Linux's package doesn't come with a systemd service file for the ClamAV milter. So I just copy it here from <a href="https://wiki.archlinux.org/index.php/ClamAV#Using_the_milter" rel="noopener noreferrer" target="_blank">ArchWiki</a>:
|
||||
|
||||
[Unit]
|
||||
Description='ClamAV Milter'
|
||||
After=clamav-daemon.service
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
ExecStart=/usr/bin/clamav-milter --config-file /etc/clamav/clamav-milter.conf
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
Save it as `/usr/lib/systemd/system/clamav-milter.service` and run `systemctl daemon-reload`.
|
||||
|
||||
Next you need to enable and start `clamav-daemon` and `clamav-milter`.
|
||||
|
||||
### 10. Greylisting with postgrey {#art-10}
|
||||
|
||||
`postgrey` is being configured primarily by passing arguments you configure in its service file. I go by defaults. So it is listening on `127.0.0.1:10030`.
|
||||
|
||||
So, to set a listen port pass this option: `--inet=127.0.0.1:10030`.
|
||||
|
||||
To configure greylisting duration use option `--delay=seconds`. `--max-age=N` to delete entries older than N days since the last time that they have been seen.
|
||||
|
||||
Look `perldoc postgrey` for help.
|
||||
|
||||
There are two configuaration files named `postgrey_whitelist_clients` and `postgrey_whitelist_recipients`. Dunno about other distros, but in ArchLinux they are in `/etc/postfix`. Could be in `/etc/postgrey` in other distros.
|
||||
|
||||
`postgrey_whitelist_clients` is list of trusted SMTP servers that will not be greylisted. Also there comes some problematic servers that will not attempt to send a mail again, or have a large pool of addresses. This file comes pre-filled with some known server such as `gmail.com` and `outlook.com`.
|
||||
|
||||
`postgrey_whitelist_recipients` contains a list of recipients for which mail won't be greylisted. By default there are `postmaster` and `abuse` recipients listed.
|
||||
|
||||
In postfix's `main.cf` you need just add this last line:
|
||||
|
||||
smtpd_recipient_restrictions =
|
||||
reject_unknown_recipient_domain,
|
||||
reject_non_fqdn_recipient,
|
||||
#[b check_policy_service inet:127.0.0.1:10030]
|
3
web/articles/setting_up_a_mail_server.meta
Normal file
3
web/articles/setting_up_a_mail_server.meta
Normal file
@ -0,0 +1,3 @@
|
||||
Setting up a mail server
|
||||
17 07 2022
|
||||
How to create your own mail server using Postfix and Dovecot.
|
128
web/articles/setting_up_a_tor_proxy_relay_hiddenserv.md
Normal file
128
web/articles/setting_up_a_tor_proxy_relay_hiddenserv.md
Normal file
@ -0,0 +1,128 @@
|
||||
### Contents
|
||||
|
||||
1. [Introduction](#art-1)
|
||||
2. [Installation](#art-2)
|
||||
3. [Configuration](#art-3)
|
||||
1. [Tor SOCKS/HTTP proxy](#art-3-1)
|
||||
2. [Tor relay](#art-3-2)
|
||||
3. [Hidden service](#art-3-3)
|
||||
4. [Miscellaneous](#art-4)
|
||||
1. [Nyx — status monitor for Tor nodes](#art-4-1)
|
||||
2. [Notes](#art-4-2)
|
||||
|
||||
### 1. Introduction {#art-1}
|
||||
|
||||
In this article I'll show you how to setup your own Tor proxy (SOCKS5 and HTTP), relay, and hidden service.
|
||||
|
||||
### 2. Installation {#art-2}
|
||||
|
||||
Install `tor` package using your package manager.
|
||||
|
||||
You definitely want to have control over your node and monitor it. For that purpose there is `nyx` tool. I'll cover it in 3.1 section.
|
||||
|
||||
Any program can be passed through Tor using `torify` from `torsocks` package.
|
||||
|
||||
### 3. Configuration {#art-3}
|
||||
|
||||
Tor is already bundled with a great documented `torrc-dist` file. You may just copy a `torrc-dist` file and name it as `torrc` and change what you need.
|
||||
|
||||
#### 3.1. Tor SOCKS/HTTP proxy {#art-3-1}
|
||||
|
||||
Here is an example of SOCKS/HTTP proxy settings:
|
||||
|
||||
SocksPort 192.168.0.100:9050, [ipv6 address]:9050
|
||||
HTTPTunnelPort 192.168.0.100:8118, [ipv6 address]:8118
|
||||
|
||||
SocksPolicy accept 192.168.0.0/24
|
||||
SocksPolicy accept6 [012:3fe1:337::]/48
|
||||
SocksPolicy reject *
|
||||
|
||||
BandwithRate 70MBits
|
||||
BandwithBurst 100MBits
|
||||
|
||||
ExcludeNodes {ru}, {ua}, {by}, {kz}, {??}
|
||||
ExcludeExitNodes {ru}, {ua}, {by}, {kz}, {??}
|
||||
|
||||
`SocksPort` assigns IP-address and port for SOCKS5 proxy to listen on. `HTTPTunnelPort` is for HTTP proxy. You may leave just port number to listen on all interfaces.
|
||||
|
||||
`SocksPolicy` option has the form `accept|reject IP-subnet[, ...`. It points which subnetwork is dis-/allowed to use SOCKS proxy, so there may be multiple entries. For example, `SocksPolicy accept 192.168.1.0/24` is allowing everyone from that network to use it. In order to forbid all other networks add `reject *` after all `SocksPolicy` entries. You may preffer to have them on separate lines for the sake of readability.
|
||||
|
||||
`BandwithRate` and `BandwithBurst` set the average and maximum speed of incoming and outgoing connections for proxy. `BandwithBurst` must be greater or equal to `BandwithRate`. E.g. values may look like `70MBits`, `10MBytes`, `5MB`.
|
||||
|
||||
`HTTPTunnelPort` enables HTTP proxy, set it to desireable IP:Port.
|
||||
|
||||
There are also `ExcludeNodes` and `ExcludeExitNodes` options that are the comma separated lists of forbidden nodes. There may be placed country codes, address patterns and identity fingerprints of nodes to never use in circuits. They are looking like `{ru}, {??}, 123.45.*`. I recommend to leave there at least `{??}` to forbid misconfigured nodes or nodes of an unknown origin, especially for exit nodes.
|
||||
|
||||
#### 3.2. Tor relay {#art-3-2}
|
||||
|
||||
Here is an example of relay settings.
|
||||
|
||||
ORPort 8443, [::]:8443
|
||||
Nickname Anon
|
||||
Address example.org
|
||||
ContactInfo Anon <anon@example.org>
|
||||
|
||||
RelayBandwithRate 8MBits
|
||||
RelayBandwithBurst 10MBits
|
||||
|
||||
AccountingMax 6 GB
|
||||
# Every midnight.
|
||||
AccountingStart day 00:00
|
||||
# Every 3rd day of month.
|
||||
AccountingStart month 3 00:00
|
||||
|
||||
# In case you don't want to be an exit node.
|
||||
ExitPolicy reject *:*
|
||||
|
||||
To enable a Tor relay you need to set `ORPort` option.
|
||||
|
||||
You should also provide some information. You have to set `Nickname` option that is a name of a relay. Also, optionally, yet recommended, you may fill `ContactInfo` option with your e-mail address.
|
||||
|
||||
If you leave your e-mail address Tor weather service will send you a notification if your node goes down.
|
||||
|
||||
You can also set `Address` option if you have a domain name or set it to your white IP-address. Otherwise, if you don't add it or comment out it, Tor will guess it.
|
||||
|
||||
`RelayBandwithRate` and `RelayBandwithBurst` are the same as `BandwithRate` and `BandwithBurst` but for relay.
|
||||
|
||||
Add `ExitPolicy reject *:*` to disable exit node if you don't need it. I found out that setting `ExitRelay` to 0 doesn't disable an exit node, so you must add rejecting policy.
|
||||
|
||||
`AccountingMax` and `AccountingStart` are used to limit traffic for given period.
|
||||
|
||||
#### 3.3. Hidden service {#art-3-3}
|
||||
|
||||
There are two mandatory options to work with: `HiddenServiceDir` and `HiddenServicePort`.
|
||||
|
||||
Of course, there are many other options, e.g. client authentication. But in simple case all you need are those two options above.
|
||||
|
||||
Every hidden service starts with `HiddenServiceDir <path>` directory that contains public and secret keys, hostname for a hidden service and a directory called `authorized_clients` that stores info on all clients that are authorized to access this hidden service.
|
||||
|
||||
And at least one `HiddenServicePort <tor port> <host:port of service>` sets port to listen to in Tor network as first parameter and the second one is a service that you want to give access from Tor to. E.g. `HiddenServicePort 80 localhost:8201` for webserver.
|
||||
|
||||
It allows you to give access to many services by one Tor hostname.
|
||||
|
||||
Example:
|
||||
|
||||
HiddenServiceDir /var/lib/tor/hidden-services/website
|
||||
HiddenServicePort 80 localhost:8201
|
||||
HiddenServicePort 25 192.168.1.160:25
|
||||
|
||||
### 4. Miscellaneous {#art-4}
|
||||
|
||||
#### 4.1. Nyx — status monitor for Tor nodes {#art-4-1}
|
||||
|
||||
You have to set `ControlPort` option to desired port, it will listen on localhost. If you need access from outside then set it to IP:9051. Also, you need to set `DisableDebuggerAttachment` option to 0, otherwise you'll not be able to use nyx. At least in my case nyx cannot connect with this option being set to 1.
|
||||
|
||||
Example:
|
||||
|
||||
ControlPort 192.168.1.200:9051
|
||||
DisableDebuggerAttachment 0
|
||||
|
||||
You may install it using package manager, but guaranteed last version can be installed from Python's `pip` package manager (`pip install nyx`).
|
||||
|
||||
#### 4.2. Notes {#art-4-2}
|
||||
|
||||
I hope you have a static IP-address or your IP changes once a month at least, otherwise you'll never become a guard (entry) node.
|
||||
|
||||
An option `AvoidDiskWrites` is usefull in case you're running from SSD or SD card.
|
||||
|
||||
You have to make a backup of `/var/lib/tor/keys` folder to save your node's cryptographic identity keys. They are used to identify your node. You can see stats on your node at <a href="https://metrics.torproject.org" rel="noopener noreferrer" target="_blank">metrics.torproject.org</a>. To find your node use what you put in `Nickname` parameter or a fingerprint that is shown in nyx.
|
@ -0,0 +1,3 @@
|
||||
Setting up a Tor proxy, relay and hidden service
|
||||
15 08 2020
|
||||
How to setup a Tor proxy, relay and hidden service.
|
Loading…
Reference in New Issue
Block a user