You are on page 1of 9

Basic server configuration notes

-----------------------------------

For home or cloud servers depend on ports availables where every services will be directly hosted.
This configuration is not the most secure, if both, services or pf are misconfigured, the integrity
of the operating system could be compromised.

OpenBSD Installation:

Welcome to the OpenBSD/amd64 7.4 installation program.


(I)nstall, (U)pgrade, (A)utoinstall or (S)hell? I
At any prompt except password prompts you can escape to a shell by
typing '!'. Default answers are shown in []'s and are selected by
pressing RETURN. You can exit this program at any time by pressing
Control-C, but this can leave your system in an inconsistent state.

Terminal type? [vt220]


System hostname? (short form, e.g. 'foo') example

Available network interfaces are: vio0 vlan0.


Network interface to configure? (name, lladdr, '?', or 'done') [vio0]
IPv4 address for vio0? (or 'autoconf' or 'none') [autoconf]
IPv6 address for vio0? (or 'autoconf' or 'none') [none]
Available network interfaces are: vio0 vlan0.
Network interface to configure? (name, lladdr, '?', or 'done') [done]
Using DNS domainname my.domain
Using DNS nameservers at 192.168.1.1

Password for root account? (will not echo)


Password for root account? (again)
Start sshd(8) by default? [yes]
Change the default console to com0? [yes] no
Setup a user? (enter a lower-case loginname, or 'no') [no] example
Full name for user example? [example]
Password for user example? (will not echo)
Password for user example? (again)
WARNING: root is targeted by password guessing attacks, pubkeys are safer.
Allow root ssh login? (yes, no, prohibit-password) [no]
What timezone are you in? ('?' for list) [America/Montreal]

Available disks are: sd0.


Which disk is the root disk? ('?' for details) [sd0]
Encrypt the root disk with a passphrase? [no]
No valid MBR or GPT.
Use (W)hole disk MBR, whole disk (G)PT or (E)dit? [whole]
Setting OpenBSD MBR partition to whole sd0...done.
The auto-allocated layout for sd0 is:
# size offset fstype [fsize bsize cpg]
a: 1190.2M 64 4.2BSD 2048 16384 1 # /
b: 256.0M 2437568 swap
c: 10240.0M 0 unused
d: 3072.0M 2961856 4.2BSD 2048 16384 1 # /usr
e: 2048.0M 9253312 4.2BSD 2048 16384 1 # /home
Use (A)uto layout, (E)dit auto layout, or create (C)ustom layout? [a] c
Label editor (enter '?' for help at any prompt)
sd0> p
OpenBSD area: 64-20971520; size: 20971456; free: 20971456
# size offset fstype [fsize bsize cpg]
c: 20971520 0 unused
sd0> a a
offset: [64]
size: [20971456] 9GO
FS type: [4.2BSD]
mount point: [none] /
sd0*> a b
offset: [18876352]
size: [2095168]
FS type: [swap]
sd0*> p
OpenBSD area: 64-20971520; size: 20971456; free: 0
# size offset fstype [fsize bsize cpg]
a: 18876288 64 4.2BSD 2048 16384 1 # /
b: 2095168 18876352 swap
c: 20971520 0 unused
sd0*> w
sd0> q
No label changes.
/dev/rsd0a: 9216.9MB in 18876288 sectors of 512 bytes
46 cylinder groups of 202.50MB, 12960 blocks, 25920 inodes each
/dev/sd0a (50dc3a18eb2c0fba.a) on /mnt type ffs (rw, asynchronous, local)

Let's install the sets!


Location of sets? (cd0 disk http nfs or 'done') [cd0]
Pathname to the sets? (or 'done') [7.4/amd64]

Select sets by entering a set name, a file name pattern or 'all'. De-select
sets by prepending a '-', e.g.: '-game*'. Selected sets are labelled '[X]'.
[X] bsd [X] comp74.tgz [X] xbase74.tgz [X] xserv74.tgz
[X] bsd.rd [X] man74.tgz [X] xshare74.tgz
[X] base74.tgz [X] game74.tgz [X] xfont74.tgz
Set name(s)? (or 'abort' or 'done') [done]
Directory does not contain SHA256.sig. Continue without verification? [no] yes
Installing bsd 100% |**************************| 24750 KB 00:02
Installing bsd.rd 100% |**************************| 4550 KB 00:00
Installing base74.tgz 100% |**************************| 368 MB 01:23
Extracting etc.tgz 100% |**************************| 257 KB 00:00
Installing comp74.tgz 100% |**************************| 75644 KB 00:24
Installing man74.tgz 100% |**************************| 7831 KB 00:03
Installing game74.tgz 100% |**************************| 2748 KB 00:01
Installing xbase74.tgz 100% |**************************| 57135 KB 00:16
Extracting xetc.tgz 100% |**************************| 7266 00:00
Installing xshare74.tgz 100% |**************************| 4578 KB 00:02
Installing xfont74.tgz 100% |**************************| 22968 KB 00:05
Installing xserv74.tgz 100% |**************************| 14951 KB 00:03
Location of sets? (cd0 disk http nfs or 'done') [done]
Saving configuration files... done.
Making all device nodes... done.
fw_update:fw_update: firmware.openbsd.org: no address associated with name
add none; update none
Cannot fetch http://firmware.openbsd.org/firmware/7.4/SHA256.sig
Relinking to create unique kernel...
done.

CONGRATULATIONS! Your OpenBSD install has been successfully completed!

When you login to your new system the first time, please read your mail
using the 'mail' command.

Exit to (S)hell, (H)alt or (R)eboot? [reboot]

- You will to remark "/" and "swap" partition only. With about 10G disk space you could result full
disk space if you separate into multiple partitions.
- Once terminated, reboot and connect with your login/password

# ssh -l example 192.168.1.2


The authenticity of host '192.168.1.2 (192.168.1.2)' can't be established.
ED25519 key fingerprint is SHA256:hwgUnJZkGm+/3KDlB33dbOOAVBiVYEqkpLhVIKH/0eg.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.1.2' (ED25519) to the list of known hosts.
example@192.168.1.2's password:
OpenBSD 7.4 (GENERIC) #1336: Tue Oct 10 08:52:22 MDT 2023

Welcome to OpenBSD: The proactively secure Unix-like operating system.

Please use the sendbug(1) utility to report bugs in the system.


Before reporting a bug, please try to reproduce it with the latest
version of the code. With bug reports, please try to ensure that
enough information to reproduce the problem is enclosed, and if a
known fix for it exists, include that as well.

example$ nslookup google.ca


Server: 192.168.1.1
Address: 192.168.1.1#53
Non-authoritative answer:
Name: google.ca
Address: 172.217.13.163

example$ su
Password:
example# echo "permit nopass :wheel" > /etc/doas.conf
example# exit
example$ doas syspatch
Get/Verify syspatch74-001_xserver... 100%
|**************************************************************************************************
***| 4466 KB 00:00
Installing patch 001_xserver
Get/Verify syspatch74-002_msplit.tgz 100%
|**************************************************************************************************
***| 93204 00:00
Installing patch 002_msplit
Relinking to create unique kernel... done; reboot to load the new kernel
Errata can be reviewed under /var/syspatch
example$ doas fw_update
fw_update: add intel; update none
example$ doas pkg_add ee
example$ doas reboot

We have apply patch, configured doas and installed favorite text editor.
Now let's make initial configuration to the /etc/pf.conf

example$ doas ee /etc/pf.conf


ext_if = "em0"
ext_ip = "192.168.1.2"
table <martians> { 0.0.0.0/8 10.0.0.0/8 127.0.0.0/8 169.254.0.0/16 \
172.16.0.0/12 192.0.0.0/24 192.0.2.0/24 224.0.0.0/3 \
192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 \
203.0.113.0/24 }
set block-policy drop
set loginterface egress
set skip on lo0
match in all scrub (no-df random-id max-mss 1440)
antispoof quick for { egress }
block in quick on egress from <martians> to any
block return out quick on egress from any to <martians>
block all
pass out quick inet
pass in on $ext_if inet proto tcp from any to $ext_ip port { 22 } # Sshd
pass in on $ext_if inet proto { tcp udp } from any to $ext_ip port { 53 } # Nsd
pass in on $ext_if inet proto tcp from any to $ext_ip port { 80 443 } # Http/s
pass in on $ext_if inet proto tcp from any to $ext_ip port { 25 465 587 993 } # Mail

example$ doas pfctl -f /etc/pf.conf

Next, configure the domains name:

example$ doas rm /var/nsd/nsd.conf


example$ doas ee /var/nsd/etc/nsd.conf
# $OpenBSD: nsd.conf,v 1.13 2018/08/16 17:59:12 florian Exp $
# Replace 192.168.1.2 by a public IP and example.org by your domain name
server:
hide-version: yes
verbosity: 1
database: "" # disable database
ip-address: 192.168.1.2
logfile: "/var/log/nsd.log"

remote-control:
control-enable: yes
control-interface: /var/run/nsd.sock

zone:
name: "example.org"
zonefile: "/zones/master/example.org.zone"
zone:
name: "1.168.192.IN-ADDR.ARPA"
zonefile: "/zones/master/1.168.192.zone"

example$ doas ee /var/nsd/zones/master/example.org.zone


@ IN SOA ns1.example.org. hostmaster.example.org. (
2023092105 ; serial
1h ; refresh
30m ; retry
14d ; expire
1h ) ; negative

IN NS ns1.example.org.
IN NS ns2.example.org.
IN MX 10 mail.example.org.
ns1 IN A 192.168.1.2
ns2 IN A 172.16.1.2
mail IN A 192.168.1.2
www IN A 192.168.1.2
@ IN A 192.168.1.2
IN TXT "v=spf1 ip4:192.168.1.2 ~all"

example$ doas ee /var/nsd/zones/master/1.168.192.zone


$TTL 2d ; 172800 secs
$ORIGIN 1.168.192.IN-ADDR.ARPA.
@ IN SOA ns1.example.org. hostmaster.example.org. (
2023092105 ; serial number
12h ; refresh
30m ; update retry
14d ; expiry
3h ; NXDOMAIN ttl
)
IN NS ns1.example.org.
IN NS ns2.example.org.
2 IN PTR example.org. ; FDQN

example$ doas rcctl enable nsd


example$ doas rcctl start nsd

- Once name server is hosting example.org, we can configure the web server to generate letsencrypt
certificates
Be sure port 80 tcp is open and remotly visible, you have 5 try before getting banned 1 hour. Most
of problems come
from filtred port 80.

example$ doas ee /etc/acme-client.conf


authority letsencrypt {
api url "https://acme-v02.api.letsencrypt.org/directory"
account key "/etc/ssl/private/letsencrypt.key"
}
domain www.example.org {
domain key "/etc/ssl/private/www.example.org.key"
domain certificate "/etc/ssl/www.example.org.crt"
domain full chain certificate "/etc/ssl/www.example.org.pem"
sign with letsencrypt
}

example$ doas rm /etc/httpd.conf


example$ doas ee /etc/httpd.conf
server "example.org" {
root "/htdocs/www.example.org"
listen on * port 80
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
location * {
block return 302 "https://$HTTP_HOST$REQUEST_URI"
}
}

example$ doas rcctl enable httpd


example$ doas rcctl start httpd
example$ doas acme-client -v example.org

We have now certificates from Letsencrypt, lets reconfigure /etc/httpd.conf to use them for https

example$ doas ee /etc/httpd.conf


server "example.org" {
root "/htdocs/www.example.org"
listen on * port 80
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
location * {
block return 302 "https://$HTTP_HOST$REQUEST_URI"
}
}
server "example.org" {
root "/htdocs/www.example.org"
listen on * tls port 443
tls {
certificate "/etc/ssl/www.example.org.pem"
key "/etc/ssl/private/www.example.org.key"
}
location "/htdocs/www.example.org/*" {
directory auto index
}
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
}

Restart the httpd server and check url https://www.example.org


example$ rcctl restart httpd

- We want mail services with its own certificates, so we have to make change in /etc/acme-
client.conf for mail.example.org

example$ doas ee /etc/acme-client.conf


authority letsencrypt {
api url "https://acme-v02.api.letsencrypt.org/directory"
account key "/etc/ssl/private/letsencrypt.key"
}
domain mail.example.org {
domain key "/etc/ssl/private/mail.example.org.key"
domain certificate "/etc/ssl/mail.example.org.crt"
domain full chain certificate "/etc/ssl/mail.example.org.pem"
sign with letsencrypt
}

example$ doas acme-client -v mail.example.org


- OpenSMTPd setup

example$ doas pkg_add opensmtpd-filter-senderscore opensmtpd-filter-dkimsign


example$ cd /etc/mail

- Create rsa key on the domain name server, this key should be copied to the mail server
example$ doas -u _dkimsign openssl genrsa -out /etc/mail/dkim/private.rsa.key 2048

- Create the rsa key to be placed in the domain zone


example$ doas openssl rsa -in /etc/mail/dkim/private.rsa.key -pubout | sed
'1s/.*/v=DKIM1;p=/;:nl;${s/-----.*//;q;};N;s/\n//g;b nl;'

Modify /var/nsd/zones/master/example.org.zone ( see domain.zone(dkim)) to add dkim key generated.


- Add _dmarc TXT, the mail you want the dmarc report send erreur messages
- Add the spf TXT, the IP of the domain name
- In the domain zone, example._domainkey -> example is the selector, this is an identification, use
what you want simple.

example$ doas ee /var/nsd/zones/master/example.org.zone


@ IN SOA ns1.example.org. hostmaster.example.org. (
2023092105 ; serial
1h ; refresh
30m ; retry
7d ; expire
1h ) ; negative

IN NS ns1.example.org.
IN NS ns2.example.org.
IN MX 10 mail.example.org.
ns1 IN A 192.168.1.2
ns2 IN A 172.16.1.2
mail IN A 192.168.1.2
www IN A 192.168.1.2
@ IN A 192.168.1.2
IN TXT "v=spf1 ip4:192.168.1.2 ~all"
_dmarc IN TXT "v=DMARC1;p=quarantine; pct=100;
rua=mailto:dmarcreport@example.org"
example._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MFDSwerereferferwgrtgrtjrwjrtigwtijgpwijtgpwijtpgwijrgtpjwprgtojiwprtgijopwrtigjpwrjgtipworjgtio
pwrgtijpowrjtgiorwtgijorwtgjwporgjwrotgjowrtjgpwortjgowrjtgowrijtgopwrjtgopwrtjgwortgjopwrtgjpowrtg
jpworgtjpwrjtgporwgtjworgjorwjgtporgtjwpgtjwrgtpwrjgoprwjw"
"fdsfTETevsfwfvkw^vjtjgwdmvs;lfvrt^tvmslvmw^vmwvw^vmdfl;vw^;vlrmw^mvlw^vl^dflv,wvrnvjrivkjvsvvslwvi
rvwrvlwkvwkvddsjlsjkfsjdfqjjfpqfjpreqjpqr" )

example$ doas ee /etc/mail/smtpd.conf


# /etc/mail/smtpd.conf
# TLS certificate ------------------------------------------------------
pki mail cert "/etc/ssl/mail.example.org.crt"
pki mail key "/etc/ssl/private/mail.example.org.key"

# Incoming mail filters ------------------------------------------------


filter "rdns" phase connect match !rdns disconnect "550 Bye."
filter "fcrdns" phase connect match !fcrdns disconnect "550 Bye."
filter "senderscore" proc-exec "/usr/local/libexec/smtpd/filter-senderscore -blockBelow 10 -
junkBelow 70 -slowFactor 1000"
filter "dkimsign_rsa" proc-exec "filter-dkimsign -d razorlabs.ovh -s razorlabs -k
/etc/mail/dkim/private.rsa.key" user _dkimsign group _dkimsign
filter "rspamd" proc-exec "filter-rspamd"

# Domain and email tables ----------------------------------------------


table vdomains file:/etc/mail/vdomains
table vusers file:/etc/mail/vusers

# Listeners ------------------------------------------------------------
listen on socket filter dkimsign_rsa
listen on all tls pki mail filter { "dkimsign_rsa", "rdns", "fcrdns", "senderscore", "rspamd" }
listen on all port submission tls-require pki mail auth mask-src filter { "rspamd", "dkimsign_rsa"
}

# Actions to process ---------------------------------------------------


action "local_mail" maildir junk virtual <vusers>
action "outbound" relay helo mail.example.org

match from any for domain <vdomains> action "local_mail"


match from any auth for any action "outbound"
match from local for local action "local_mail"
match from local for any action "outbound"
#end of smtpd.conf

- Domains names that are allowed for mail, may have more than one

example$ doas ee /etc/mail/vdomains


example.org

- Users that have an email

example$ doas ee /etc/mail/vusers


mailuser@example.org mailuser # mailuser@example.org mail address point to the local user
mailuser
virtualuser@example.org mailuser@example.org # this virtual user point to a local user mailuser ->
mailuser@example.org

- Specify the mail server name

example$ doas ee /etc/mail/mailname


mail.example.org

- Rspamd Setup

example$ doas pkg_add rspamd--hyperscan opensmtpd-filter-rspamd redis


example$ doas ee /etc/rspamd/local.d/redis.conf
servers = "127.0.0.1";

example$ doas ee /etc/rspamd/local.d/greylist.conf


servers = "127.0.0.1:6379";

example$ doas /etc/rspamd/local.d/spf.conf


spf_cache_size = 1k;
spf_cache_expire = 1d;
max_dns_nesting = 10;
max_dns_requests = 30;
min_cache_ttl = 5m;

example$ doas ee /etc/rspamd/local.d/dkim_signing.conf


allow_username_mismatch = true; # this will allow opensmtpd simple username to pass dkim signing to
rspamd
domain {
example.org {
path = "/etc/mail/dkim-example.org.key";
selector = "example";
}
}

example$ doas rcctl enable redis


example$ doas rcctl start redis
example$ doas rcctl enable rspamd
example$ doas rcctl start rspamd

- Dovecot Setup

example$ doas pkg_add dovecot dovecot-pigeonhole


example$ doas ee /etc/dovecot/conf.d/10-mail.conf
# Change the line similar to
mail_location = maildir:~/Maildir

example$ doas ee /etc/dovecot/conf.d/10-master.conf


# change imap-login for port 0
service imap-login {
inet_listener imap {
port = 0

example$ doas ee /etc/dovecot/conf.d/10-ssl.conf


# find and replace
ssl = yes
ssl_cert = </etc/ssl/mail.example.org.crt
ssl_key = </etc/ssl/private/mail.example.org.key

example$ doas ee /etc/dovecot/conf.d/20-imap.conf


# mostly at the end of file, find and replace
mail_plugins = $mail_plugins imap_sieve zlib
mail_max_userip_connections = 50

example$ doas rm /etc/dovecot/conf.d/90-plugin.conf


example$ doas ee /etc/dovecot/conf.d/90-plugin.conf
# replace with the following

plugin {
zlib_save = zstd

sieve_plugins = sieve_imapsieve sieve_extprograms


sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment

# Spam: move from anywhere to Junk or flag changed in Junk


imapsieve_mailbox1_name = Junk
imapsieve_mailbox1_causes = COPY APPEND FLAG
imapsieve_mailbox1_before = file:/usr/local/lib/dovecot/sieve/report-spam.sieve

# Ham: move from Junk to anywhere


imapsieve_mailbox2_name = *
imapsieve_mailbox2_from = Junk
imapsieve_mailbox2_causes = COPY
imapsieve_mailbox2_before = file:/usr/local/lib/dovecot/sieve/report-ham.sieve

sieve_pipe_bin_dir = /usr/local/lib/dovecot/sieve
}

example$ doas ee /usr/local/lib/dovecot/sieve/report-spam.sieve


require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
if environment :matches "imap.user" "*" { set "username" "${1}"; }
pipe :copy "sa-learn-spam.sh" [ "${username}" ];

example$ doas ee /usr/local/lib/dovecot/sieve/report-ham.sieve


require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
if environment :matches "imap.user" "*" { set "username" "${1}"; }
pipe :copy "sa-learn-ham.sh" [ "${username}" ];

example$ doas ee /usr/local/lib/dovecot/sieve/sa-learn-spam.sh


exec /usr/local/bin/rspamc learn_spam

example$ doas ee /usr/local/lib/dovecot/sieve/sa-learn-ham.sh


exec /usr/local/bin/rspamc learn_ham

example$ cd /usr/local/lib/dovecot/sieve/
example$ doas chmod 0755 *sh
example$ doas sievec report-ham.sieve
example$ doas sievec report-spam.sieve
example$ doas rcctl enable dovecot
example$ doas rcctl start dovecot
example$ doas rcctl restart nsd smtpd redis rspamd dovecot

If errors, debug with the following commands:

example$ doas smtpd -dvn


example$ doas smtpd -d -T smtp -v -f /etc/mail/smtpd.conf
example$ doas rspamd

Verify /var/log/messages and /var/log/maillog for messages errors

You might also like