Categories

Donate

Advert

RAM Speed according to Memtest86+

Here are some speed results for RAM according to Memtest86+ on some machines that I have run. Note that the reported speed varies between runs by a few percent.

Thinkpad 600e PentiumII 400Mhz PC-66 RAM (2 DIMMs) 174MB/s
Compaq P3-866MHz PC133 RAM (3 DIMMs, 2*128 + 256) 190MB/s
Compaq Athlon 1GHz PC133 RAM (3 DIMMs) 219MB/s
Compaq P3-800MHz PC133 RAM (1 DIMM) 270MB/s
Compaq P3-800MHz PC133 RAM (3 DIMMs, 2*128 + 256) 240MB/s
Compaq P4 1.5GHz PC133 RAM (3 DIMMs) 486MB/s
Compaq P4 1.5GHz PC133 RAM (1 or 2 DIMMs) 490MB/s
EeePC 701, DDR2-665 PC2-5300 running at DDR2-333 speed 798MB/s
HP Celeron 1.8GHz PC2100/DDR266 (1 DIMM) 824MB/s
HP Celeron 2.4GHz PC2100/DDR266 RAM (2 DIMMs) 984MB/s
Celeron D (32bit) 2.93GHz PC2400/DDR300 PC3200 RAM 1,140MB/s
HP Celeron 2.4GHz PC2700/DDR333 RAM (2 DIMMs) 1,027MB/s
HP Celeron 2.4GHz PC2700/DDR333 RAM (2 DIMMs) 1,375MB/s
Dell PowerEdge T105 Dual-core Opteron 1212 (2GHz) single DDR2-667 ECC RAM 1,670MB/s
Dell PowerEdge T105 Dual-core Opteron 1212 (2GHz) pair of DDR2-667 ECC RAM 1,826MB/s
NEC Pentium E2160 1.8GHz DDR663 (two mismatched DIMMs) 2,307MB/s
IBM Pentium E2160 1.8GHz DDR2-667 PC2-5300 (single DIMM) 2,371MB/s
IBM Pentium E2160 1.8GHz PC2-4200 (paired DIMMs) 2,436MB/s
NEC Pentium E4600 2.4GHz DDR2-667 PC2-5300 (single DIMM) 2,528MB/s
NEC Pentium D 2.8GHz DDR 533 (unpaired DIMMS) 1,600MB/s
NEC Pentium D 2.8GHz DDR 533 (paired DIMMS) 2,600MB/s
Thinkpad T61 DDR2-665 PC2-5300 (single DIMM) 2,023MB/s
Thinkpad T61 DDR2-665 PC2-5300 (paired or mismatched DIMMs) 2,823MB/s
Core Gen2 2492MHz 3,804MB/s
Core Gen2 2492MHz 2 DIMMs 3,930MB/s
Q8400 2*PC6400 4,830MB/s
Dell PowerEdge T320 E5-2430 2.2GHz, DDR3-1600 PC3-12800 (single DIMM) 7,692MB/s
Intel X3450 2.67GHz, DDR3-1066 (4 DIMMs) 10.0GB/s
Thinkpad X1 Yoga Gen3 i5-8350U 1.7GHz, LPDDR3-2133 (paired DIMMs) Battery/AC 7,140MB/s 10.3GB/s
Dell PowerEdge T320 E5-2430 2.2GHz, DDR3-1600 PC3-12800 (pair DIMMs) 11.3GB/s
Dell Lattitude 5590 laptop I5-8350U 1.7GHz, DDR4-2400 PC4-19200 (paired DIMMs) 12.2GB/s
Dell PowerEdge T30 Core E3-1225 3.3GHz, DDR4-2133 PC4-17000 (single DIMM) 12.5GB/s
Dell PowerEdge T320 E5-2430 2.2GHz, DDR3-1600 PC3-12800 (3 DIMMs) 13.5GB/s
Dell Latitude 7480 i7-7660U, DDR4-2400 (paired DIMMs) 13.7GB/s
Dell Lattitude 7410 Laptop i7-10610U DDR4 14.6GB/s
Dell Lattitude 7400 2in1 Laptop i7-8665U DDR3 14.8GB/s
HP Z640 E5-1650v3, DDR4 (paired DIMMs) 15.5GB/s
Thinkpad X1 Carbon Gen5 i5-6300U 2.40GHz, DDR3-1867 (paired DIMMs) Battery/AC 7,640MB/s 16.2GB/s
i7-2600 3.4GHz, DDR3-1333 PC3-10600 (paired DIMMs) 16.6GB/s
AMD Ryzen 5 3600 DDR4-3200 (4*8G DIMMs) 17.3GB/s
Dell PowerEdge T110-II Core i3-3220 3.3GHz, DDR3-1600 PC3-12800 (paired DIMMs) 17.9GB/s

The Wikipedia page on SDRAM lists the theoretical speeds and the various names of the different types of DDR RAM (each type seems to have at least two names).

DDR266 theoretically can do 2100MB/s, but I’ve only seen it do 984MB/s (with two DIMMs).

References

Politics

Wikileaks/Assange supports Russia

How to Talk to Science Deniers

Pro-lifers really want misogyny

A short summary of bad things that Trump did with full support from conservatives

Fake news is almost entirely a right wing thing

PsyPost has an interesting article on the correlation between watching Fox News and lacking knowledge of science and of society

Reserve Bank of Australia inflation calculator

Australian reserve bank interest rates in the past

To The Next Mass Shooter, A Modest Proposal is an insightful comment on mass shootings

The Al Capone theory of sexual harassment

The Right Wing in a Few WordsThey can tell people what to do, no-one can tell them what to do, etc

Nick Fuentes “sex with women is gay”

News Tribune, Dove of Oneness and NESARA

Libertarians

The modern definition of the word “Libertarian” means anarcho-capitalist

Ayn Rand was a sociopath who admired a serial killer

Murray Rothbard believed that parents should be allowed to starve their children to death

A Libertarian walks into a bear, Libertarians take over a town and get attacked by bears

Galt Gulch Chile, one of the failed attempts at a Libertarian town

Psychology

“Why I Make Terrible Decisions, Or, Poverty Thoughts” is an essay by Linda Tirado AKA killermartinis about her experiences with poverty in the US. A large part of this is addressing advice offered by well-meaning people who don’t know what it’s like and isn’t helpful.

Religion

Why Evangelism aims to alienate the non-believers

Has “Homosexual” Always Been in the Bible? No, it was originally about pedophilia.

The Only Moral Abortion is My Abortion – when anti-choice women choose abortion.

The Henry Walker villains wiki page shows the depravity of Jack Chick

Evangelicals believe that Hitler was sent by God

7 Tenets of Satanism

1969 Christmas Mass Incident – how to do communion epically

The different theologies of Jesus and Paul

Science

Things I won’t Work With – blog posts about nasty chemicals like FOOF and ClF3

How a Brisbane school limited the spread of Covid though checking air quality.

Foreign Accent Syndrome, accents can be based on brain issues not on learning.

Audiophiles claiming that different implementations of memcpy change the sound of audio software.

Misc/Weird

Between 5 and 10 people in the UK die each year putting on socks

Opening the “curtains of science”

Computers

How to use a phone as a desktop PC

Linux in a Pixel Shader, how to run a VM remotely on a GPU via VRChat without the permission of the receiver

Work

Why unstructured job interviews (most job interviews) don’t work

Security

List of Red Team and Physical Entry Gear with YouTube videos

SSH Audit

Weird

Scrotum Self Repair

ETBE Mon

ETBE Mon is my fork of the traditional Unix system and network monitoring system “Mon” by Jim Trocki. My aim with this fork is to take the best patches available for the existing Mon codebase and the best “contrib” monitoring scripts and include them in one package. I also aim to write all scripts necessary for typical Linux systems. I don’t believe that a working system should involve “mon”, “mon-contrib”, and searching the net for scripts, it should be just the etbemon package.

Support

The Mon mailing list is at https://lists.coker.com.au/cgi-bin/mailman/listinfo/etbemon [1] . Please use the list instead of mailing me directly so other people can benefit from the answers.

I have created a Wiki for documenting etbemon [2].

If you need commercial support for Mon that is available too. As a basic offer for $100US by Paypal I’ll write a basic monitor script for any Linux service or RFC standard service. If there’s any other commercial support you want then just ask.

Downloads

  • Version 1.3.8. Improvements to loadavg.monitor, freespace.monitor, and sslcert.monitor.
  • Version 1.3.7. Improvements to sslcert.monitor, deleted-mapped.monitor, ps.monitor, freespace.monitor, and btrfs.monitor. Added xmpp.monitor.
  • Version 1.3.6. Added dell-temp.monitor and hp-temp.monitor to monitor server temperatures. Add -x option to ps.monitor to find process name according to Perl. Make it compile with glibc 2.32. Add selinux.monitor. Add -M option to smartctl.monitor for MegaRAID AKA PERC support and added support for NVMe devices. Improvements to imapnew.monitor deleted-mapped.monitor. Make loadavg.monitor use PSI and cgroups for more useful info.
  • Version 1.3.5. Added monitor for SMART data (smartctl). Made the sslcert check search all IPv6 and IPv4 addresses for each hostname. Make freespace check look for filesystem mountpoint. Made smtpswaks check use latest swaks command-line.
  • Version 1.3.4. Added monitor for deleted mapped files.
  • Version 1.3.3. Improved sslcert.monitor, smtpswaks.monitor, and mailxmpp.alert.
  • Version 1.3.2. Improved http.monitor, dns.monitor, zfs.monitor, freespace.monitor, sslcert.monitor, loadavg.monitor, and mailxmpp.alert. Also improved systemd support.
  • Version 1.3.1. Improvements to freespace.monitor, remote.monitor, loadavg.monitor, and msql-mysql.monitor. Increased the summary length for monshow.
  • This is the first release, numbered 1.3.0 to be higher than other releases of Mon. It is the same as the Debian version of Mon 1.2.0 (which had a dozen patches against Trocki Mon 1.2.0 from 2010).

References

Memlockd

Memlockd is a daemon that locks files into memory. Then if a machine starts paging heavily the chance of being able to login successfully is significantly increased. The default configuration will lock all the files needed for login to a Debian GNU/Linux system via the console or via ssh.

Free Short Stories

Here are some free short science-fiction stories that I enjoyed reading:

Cory Doctorow has released enough great sci-fi stories that he deserves his own section:

Robert Reed has released enough great free sci-fi stories that he deserves his own section:

Debian Repositories

Here is a list of the Debian repositories I maintain.

All my repositories support the amd64 architecture.

Buster

I’ve got a bunch of old Buster repositories. Apart from the SE Linux one I don’t think that any of them provide much benefit at this time. I’m not supporting Buster SE Linux nowadays except as a consulting service.

deb http://www.coker.com.au buster selinux
deb http://www.coker.com.au buster misc
deb http://www.coker.com.au buster wordpress

Bullseye

Bullseye are the main supported repositories at the moment. The WordPress repository is probably most useful. The misc repository has backports of mon packages and packages for my custom management scripts which are probably most useful for the source.

deb http://www.coker.com.au bullseye selinux
deb http://www.coker.com.au bullseye misc
deb http://www.coker.com.au bullseye wordpress

Bookworm

Bookworm is for the next release of Debian, probably not very useful to other people right now.

deb http://www.coker.com.au bullseye misc

SE Linux Policy Writing Training

This training exercise is based on a Debian/Bullseye system running SE Linux in a default configuration in Enforcing mode. To set it up put the following in /usr/local/sbin/adaemon.sh and make it mode 0755:

#!/bin/bash

echo -100 > /proc/$$/oom_score_adj

while true ; do
  /sbin/runuser -u nobody -- /bin/nc -q0 -l -p 4000 < $0
  /bin/sleep 1
done

Then put the following in /etc/systemd/system/adaemon.service:

[Unit]
Description=a daemon

[Service]
RestartSec=20
Restart=always
ExecStart=/usr/local/sbin/adaemon.sh
StandardOutput=syslog
KillMode=mixed
Type=simple

[Install]
WantedBy=multi-user.target

To start it run the following commands:

systemctl enable adaemon.service
systemctl start adaemon.service
  1. Under the /root/pol directory create the file adaemon.fc:

    /usr/local/sbin/adaemon.sh -- gen_context(system_u:object_r:adaemon_exec_t,s0)

    Under the /root/pol directory create the file adaemon.te:

    policy_module(adaemon,1.0.0)
    
    #require {
    #}
    
    type adaemon_t;
    type adaemon_exec_t;
    init_daemon_domain(adaemon_t, adaemon_exec_t)
  2. After creating those files run the command "make load" (notice there is a symlink for the Makefile). That command compiles the policy module adaemon.pp and loads it into the running policy.

    After loading the policy run "restorecon -v /usr/local/sbin/adaemon.sh" to label the file, note that it should tell you that it has labelled it as adaemon_exec_t.

  3. The daemon is still running, run the command "nc localhost 4000" on your VM to observe it's output.

    Run the command "ps axZ|grep init_t" to see processes running as init_t (should only be process 1), in this case adaemon.sh is running in the wrong context.

  4. Try to restart the daemon (which will fail) and analyse the audit log for actions that were denied:

    systemctl restart adaemon
    systemctl status adaemon
    audit2allow -l < /var/log/audit/audit.log
  5. To generate rules suitable for adding to policy the command "audit2allow -l < /var/log/audit/audit.log -R" should be used, the "-R" means to generate policy using macros. The first rule it will suggest adding is:

    corecmd_shell_entry_type(adaemon_t)

    Add the above rule to adaemon.te and run the following commands:

    make load
    systemctl restart adaemon
    systemctl status adaemon
    audit2allow -l < /var/log/audit/audit.log -R

    The above audit2allow gives the following output:

    corecmd_search_bin(adaemon_t)
    files_read_etc_files(adaemon_t)
    miscfiles_setattr_localization(adaemon_t)

    Setting the attributes of the localization files is not what we want the daemon to do. If you run the command "audit2allow -l < /var/log/audit/audit.log -R -v" it gives a list of all the possible macros that can be used, for the localization access one of the options is miscfiles_read_localization which is a good match for what you expect the daemon to need.

  6. corecmd_search_bin(adaemon_t)
    files_read_etc_files(adaemon_t)
    miscfiles_read_localization(adaemon_t)

    Add the above to adaemon.te and run the following commands:

    make load
    systemctl restart adaemon
    systemctl status adaemon
    audit2allow -l < /var/log/audit/audit.log -R
  7. After the previous change the audit2allow output is:

    corecmd_check_exec_bin_files(adaemon_t)

    This is something we want, but checking whether programs are executable isn't sufficient. Run the command "audit2allow -l < /var/log/audit/audit.log -R -v" and you will see that one of the options given is "corecmd_exec_bin(adaemon_t)". So add the following to adaemon.te:

    corecmd_exec_bin(adaemon_t)

    After adding that rule run the following commands:

    make load
    systemctl restart adaemon
    systemctl status adaemon
    audit2allow -l < /var/log/audit/audit.log -R

    Below is the output of audit2allow:

    allow adaemon_t self:capability { setgid sys_resource };
    allow adaemon_t self:netlink_audit_socket create;
    allow adaemon_t self:unix_dgram_socket create;
    kernel_read_system_state(adaemon_t)
    kernel_search_fs_sysctls(adaemon_t)
  8. Add the output of audit2allow from the previous step and run:
    make load
    systemctl restart adaemon
    systemctl status adaemon
    audit2allow -l < /var/log/audit/audit.log -R

    That will give the following output:

    allow adaemon_t self:netlink_audit_socket write;
    allow adaemon_t self:unix_dgram_socket connect;
    kernel_read_kernel_sysctls(adaemon_t)

    Add the above to adaemon.te. You can remove the "kernel_search_fs_sysctls(adaemon_t)" line as that's included in the kernel_read_kernel_sysctls macro, or you could leave it as it doesn't do any harm. Then run the following:

    make load
    systemctl restart adaemon
    systemctl status adaemon
    audit2allow -l < /var/log/audit/audit.log -R
  9. allow adaemon_t init_runtime_t:dir search;
    allow adaemon_t self:netlink_audit_socket nlmsg_relay;

    The audit2allow command from the previous step gave the above output. Access to init_runtime_t shouldn't be needed and would need a require statement in the policy. So just add the following line to adaemon.te:

    allow adaemon_t self:netlink_audit_socket nlmsg_relay;

    Then run the following commands:

    make load
    systemctl restart adaemon
    systemctl status adaemon
    audit2allow -l < /var/log/audit/audit.log -R
  10. allow adaemon_t init_runtime_t:dir search;
    allow adaemon_t self:capability audit_write;
    allow adaemon_t self:netlink_audit_socket read;

    The audit2allow from the previous step gave the above. Now as the source of the daemon is visible it would be good to know how that maps to an audit socket. To discover that run the following command:

    grep netlink_audit_socket /var/log/audit/audit.log

    That shows that runuser is the responsible program. It makes sense that a program which is designed to change privileges of a child process will need audit access to log what it does, so this is correct.

    Add the following to adaemon.te:

    allow adaemon_t self:capability audit_write;
    allow adaemon_t self:netlink_audit_socket read;

    Then run the following commands:

    make load
    systemctl restart adaemon
    systemctl status adaemon
    audit2allow -l < /var/log/audit/audit.log -R
  11. allow adaemon_t init_runtime_t:dir search;
    allow adaemon_t init_t:dir search;
    allow adaemon_t self:capability setuid;
    allow adaemon_t self:process { setrlimit setsched };

    The output from audit2allow in the previous step is above. The init_t and init_runtime_t lines aren't needed (the macro init_daemon_domain gives all the init interaction the daemon needs), so add the following to the policy:

    allow adaemon_t self:capability setuid;
    allow adaemon_t self:process { setrlimit setsched };

    Then run the following:

    make load
    systemctl restart adaemon
    systemctl status adaemon
    audit2allow -l < /var/log/audit/audit.log -R
  12. allow adaemon_t self:tcp_socket create;

    The above was the only relevant output of the previous audit2allow. Allowing the daemon to create a socket alone isn't enough, what we want is to allow it to listen, accept, and transfer data. Add the following line to the policy:

    allow adaemon_t self:tcp_socket create_stream_socket_perms;

    Then run the following:

    make load
    systemctl restart adaemon
    systemctl status adaemon
    audit2allow -l < /var/log/audit/audit.log -R
  13. allow adaemon_t unreserved_port_t:tcp_socket name_bind;

    The previous step gave the above output. To address that add the following policy:

    corenet_tcp_bind_all_unreserved_ports(adaemon_t)
    corenet_tcp_bind_generic_node(adaemon_t)

    Then run the following:

    make load
    systemctl restart adaemon
    systemctl status adaemon
    audit2allow -l < /var/log/audit/audit.log -R
  14. After the previous step you should get no relevant audit2allow messages and the following command should work:
    nc -q0 localhost 4000

Postfix Training

Basic MTA Configuration

All instructions here are for Postfix. If you want to use a different MTA then you will mostly be working without instructions.

  1. To install Postfix run “apt install postfix” (or for the preconfigured images I setup reconfigure it by running “rm /etc/postfix/main.cf ; dpkg-reconfigure postfix“.
    1. Select “Internet Site” for the type of mail configuration.
    2. Enter the domain name you selected for the mail name (for the VMs I host it will be vmX.dyn.coker.com.au).
    3. When it asks for a user to receive root mail set it to the name of a test user (EG “test”). Make the user with the command “useradd -m test
    4. When it asks for a comma separated list of domains delete the default text for that field and replace it with vmX.dyn.coker.com.au.
    5. For “Force synchronous updates on mail queue” select No as apparently modern filesystems don’t need it and it significantly increases system load. If you say Yes this causes shell code equivalent to the following to be run:
      cd /var/spool/postfix
      chattr +S incoming active bounce defer deferred flush saved corrupt
    6. For “local networks” and the other settings the defaults should be good.
    7. After running the Debian package configuration create the account you specified for the root email, if it was “test” then run “useradd -m test“.
  2. The main Postfix configuration file is /etc/postfix/main.cf. Change the myhostname setting to the fully qualified name of the system, something like vmX.dyn.coker.com.au.
    You can edit /etc/postfix/main.cf with vi (or any other editor) or use the postconf command to change it, eg “postconf -e myhostname=vmX.dyn.coker.com.au“.
  3. Add “home_mailbox=Maildir/” to the Postfix configuration to make it deliver to a Maildir spool in the user’s home directory (the trailing / is important).
  4. Restart Postfix to apply the changes.
  5. Test delivery by installing swaks via “apt install swaks libio-socket-inet6-perl” and then running the command “swaks -f test@vmX.dyn.coker.com.au -t test@vmX.dyn.coker.com.au -s localhost“. Note that swaks displays the SMTP data so you can see exactly what happens and if something goes wrong you will see everything about the error.
  6. Inspect /var/log/mail.log to see the messages about the delivery. View the message which is in ~test/Maildir/new.
  7. When other students get to this stage run the same swaks command but with the -t changed to the address in their domain, check the mail.log to see that the messages were transferred and view the mail with less to see the received lines.

Certbot Configuration

To avoid password sniffing we need to use SSL for both authenticated sending of mail and for receiving mail via POP/IMAP.

Run the following commands to install letsencrypt (also the gnutls-bin utilities to test SSL and the libnet-ssleay-perl library for swaks with SSL support) and request a SSL certificate:

apt install certbot gnutls-bin libnet-ssleay-perl
letsencrypt certonly --standalone -m $EMAIL_ADDRESS -d vmX.dyn.coker.com.au

Run the command “gnutls-cli vmX.dyn.coker.com.au:25 --starttls-proto=smtp” to check the certificate used by Postfix, it should say that the certificate is not trusted.

Run the following commands to change the Postfix configuration to use the TLS certificate and then repeat the gnutls-cli command to show that it works:

postconf -e smtpd_tls_cert_file=/etc/letsencrypt/live/vmX.dyn.coker.com.au/cert.pem
postconf -e smtpd_tls_key_file=/etc/letsencrypt/live/vmX.dyn.coker.com.au/privkey.pem
postconf -e smtpd_tls_CAfile=/etc/letsencrypt/live/vmX.dyn.coker.com.au/chain.pem
postconf -e smtpd_tls_received_header=yes
postconf -e smtpd_tls_loglevel=1
systemctl restart postfix.service

To test the SMTP TLS the command go to another system and run “swaks -f test@vmX.dyn.coker.com.au -t test@vmX.dyn.coker.com.au -s vmX.dyn.coker.com.au -tls -tlsp tlsv1_3“, this specifies that the connection must be encrypted via TLS version 1.3 (the most secure SSL protocol).

Basic Pop/IMAP Configuration

All instructions here are for Dovecot. Other POP/IMAP servers are available, but there is less reason for choosing an alternative than there is for the MTA.

  1. Run “apt install dovecot-pop3d dovecot-imapd” to install Dovecot POP and IMAP servers.
    Run “netstat -tln” to see the ports that have daemons listening on them, observe that ports 110, 143, 993, and 995 are in use.
  2. Edit /etc/dovecot/conf.d/10-mail.conf and change “mail_location = mbox:~/mail:INBOX=/var/mail/%u” to “mail_location = maildir:~/Maildir“. Then restart Dovecot.
  3. Run the command “nc localhost 110” to connect to POP, then run the following commands to get capabilities, login, and retrieve mail:
    user test
    pass WHATEVERYOUMADEIT
    capa
    list
    retr 1
    quit
  4. Run the command “nc localhost 143” to connect to IMAP, then run the following commands to list capabilities, login, and logout:
    a capability
    b login test WHATEVERYOUMADEIT
    c logout
  5. For the above commands make note of the capabilities, we will refer to that later.

Now you have a basically functional mail server on the Internet!

POP/IMAP Over SSL

Edit /etc/dovecot/conf.d/10-ssl.conf, remove the following 2 lines:

ssl_cert = </etc/dovecot/private/dovecot.pem
ssl_key = </etc/dovecot/private/dovecot.key

Add the following 2 lines:

ssl_cert =</etc/letsencrypt/live/vmX.dyn.coker.com.au/fullchain.pem
ssl_key = </etc/letsencrypt/live/vmX.dyn.coker.com.au/privkey.pem

Restart Dovecot, then run the command “gnutls-cli vmX.dyn.coker.com.au:995” to connect via encrypted POP and after the connection is established you can use the same POP commands as before.

SASL

SASL is the system of SMTP authentication for mail relaying. It is needed to permit devices without fixed IP addresses to send mail through a server.

Run the following commands to configure Postfix for SASL:

# allow parts of Postfix to work with the same configuration regardless of whether they are running in a chroot
mkdir -p /var/spool/postfix/var/spool
ln -s ../.. /var/spool/postfix/var/spool/postfix
# configure Postfix for SASL with Dovecot as authentication server
postconf -e smtpd_sasl_auth_enable=yes
postconf -e smtpd_sasl_type=dovecot
postconf -e smtpd_sasl_path=/var/spool/postfix/private/auth
postconf -e broken_sasl_auth_clients=yes
postconf -e smtpd_sasl_authenticated_header=yes
systemctl restart postfix.service

Edit /etc/dovecot/conf.d/10-master.conf, uncomment the following lines, and then restart Dovecot:

unix_listener /var/spool/postfix/private/auth {
 mode = 0666
}

Edit /etc/postfix/master.cf, uncomment the line for the submission service, and restart Postfix. This makes Postfix listen on port 587 which is allowed through firewalls.

From another system (IE not the virtual machine you are working on) run “swaks -f test@vmX.dyn.coker.com.au -t YOURADDRESS -s vmX.dyn.coker.com.au -tls -tlsp tlsv1_3” (where YOURADDRESS is an address you use) and note that the message is rejected with “Relay access denied“.

Now run “swaks -f test@vmX.dyn.coker.com.au -t YOURADDRESS -s vmX.dyn.coker.com.au -tls -tlsp tlsv1_3 --auth-user test --auth-password WHATEVER and note that the message is accepted and observe that the mail is delivered (subject to anti-spam measures at the recipient).

Configuring a MUA

If every part of the previous 3 sections is complete then you should be able to setup your favourite MUA. Use “test” as the user-name for SMTP and IMAP, vmX.dyn.coker.com.au for the SMTP/IMAP server and it should just work!

Note that as the VMs I run are only accessible by SMTP and IMAP over IPv6 you need to have IPv6 on your workstation to connect. If you don’t have IPv6 then run a text mode MUA such as mutt on the VM.

Anti Spam

  1. Header checks allows rejecting mail based on known bad headers (such as blocking known spammers.
    1. Run the following command to send a test message (should work):
      swaks -f test@coker.com.au -t test@vmX.dyn.coker.com.au -s localhost
    2. Create the file /etc/postfix/header_checks with the following contents:
      /^From:.*test@coker.com.au/ REJECT

      This consists of a regular expression matching a header line and a policy (generally only REJECT makes sense).

    3. Run the following commands to enable it:
      postconf -e header_checks=regexp:/etc/postfix/header_checks
      systemctl restart postfix.service
    4. Test it with the following swaks command that should be rejected:
      swaks -f test@coker.com.au -t test@vmX.dyn.coker.com.au -s localhost
    1. Run the following command to install the postfix-policyd-spf-python package, this is a daemon that is launched by the Postfix master process for the use of other Postfix processes:
      apt install postfix-policyd-spf-python
    2. Add the following line to /etc/postfix/master.cf:
      policyd-spf  unix  -       n       n       -       0       spawn user=policyd-spf argv=/usr/bin/policyd-spf
    3. Run the following command to set the smtpd_recipient_restrictions (which hasn’t been set previously in this exercise):
      postconf -e smtpd_recipient_restrictions=permit_sasl_authenticated,permit_mynetworks,check_policy_service unix:private/policyd-spf,reject_unauth_destination
    4. Then restart postfix and SPF checks will be enabled.
    1. Run the following command to install SpamAssassin packages:
      apt install spamassassin spamc spamass-milter
    2. Configure Postfix to use SpamAssassin as a milter (a mail filter program supporting the Milter interface from Sendmail):
      postconf -e smtpd_milters=unix:/var/spool/postfix/spamass/spamass.sock
    3. Edit /etc/default/spamass-milter and set the following as the OPTIONS line:
      OPTIONS="-u spamass-milter -i 127.0.0.1 -r 5 -- -s 100485760"

      This sets a SpamAssassin score of 5 be the criteria for rejecting mail (the default for the SpamAssassin spamd daemon, spamass-milter should match spamd in this regard) and sets 10MB as the amount of data to be scanned in a message (the default is that mail that isn’t small bypasses some tests, the -s option is passed to spamc the SpamAssassin utility that talks to the daemon. Note that any typo in this line will cause things to break in unexpected ways that are difficult to debug.

    4. Run the following commands to restart all daemons and then test sending mail:
      systemctl restart spamassassin.service
      systemctl restart spamass-milter.service
      systemctl restart postfix.service
    5. Get the GTUBE spam test and try sending it to verify that spam mail is rejected:
      apt install wget
      cd /tmp
      wget https://spamassassin.apache.org/gtube/gtube.txt
      swaks -f test@vmX.dyn.coker.com.au -t test@vmX.dyn.coker.com.au -s vmX.dyn.coker.com.au --body /tmp/gtube.txt
      

      This message should be rejected because GTUBE is a standard pattern for testing anti-spam systems.

    1. Create the file /etc/tmpfiles.d/opendkim.conf with the following contents:
      d /run/opendkim 0750 opendkim opendkim - -

      Apply and verify that configuration with the following command:

      systemd-tmpfiles --create /etc/tmpfiles.d/opendkim.conf
      ls -ld /run/opendkim
    2. Run the following command to install DKIM packages:
      apt install opendkim opendkim-tools

ZFS Training Exercises

In 2015 I ran a training session on BTRFS and ZFS. Here are the notes for ZFS updated for the latest versions of everything when running on KVM. You can do all the same exercises on a non virtual machine, but it’s safest not to do this on a machine with important data. For the KVM setup I use /dev/vdc, /dev/vdd, and /dev/vde are the devices for test data.

For running ZFS on Linux in serious use I recommend having more than 4G of RAM in the system or VM that’s doing it to prevent kernel OOM issues. You should be able to complete this training exercise on a 64bit VM with 2G of RAM. To do this on Debian/Buster just replace the references to “bullseye” with “buster” in the APT configuration.

  1. Installing zfsonlinux on Debian/Bullseye
    1. Note that /etc/apt/sources.list has the following lines (the “contrib” is very important):
      deb http://mirror.internode.on.net/pub/debian/ bullseye-updates contrib main
      deb http://deb.debian.org/debian bullseye-backports contrib main
      
    2. Run the following commands:
      apt install linux-headers-amd64
      apt install -t bullseye-backports dkms spl-dkms zfs-dkms
      apt install -t bullseye-backports zfsutils-linux
      The apt command installing spl-dkms takes ages, 4 minutes real time and 9 minutes CPU time on my last test on a 4 core VM. It will take much longer if several people are doing it at the same time.
  2. Making the filesystem
    1. Create the pool:
      zpool create -o ashift=12 nyancat raidz /dev/vdc /dev/vdd /dev/vde
      NB You need to add a “-f” to overwrite the BTRFS filesystem
    2. Make some default filesystem settings:
      zfs set devices=off nyancat
      zfs set atime=off nyancat
      zfs set setuid=off nyancat
      zfs set compression=on nyancat
    3. Get information on the pool:
      zfs get all nyancat|less
      zpool list
      zpool status
    4. Make a filesystem:
      zfs create nyancat/friday
      df -h
    5. See if there are any errors, shouldn’t be any (yet):
      zpool scrub nyancat
      zpool status
    6. Copy some files to the filesystem:
      cp -r /usr /nyancat/friday
    7. Scrub the filesystem:
      zpool scrub nyancat
      zpool status
    1. Online corruption

    2. Corrupt the filesystem:
      dd if=/dev/zero of=/dev/vdd bs=1024k count=2000 seek=50
    3. Scrub again, should give a warning about errors:
      zpool scrub nyancat
      zpool status
    4. Verify that the data is intact:
      diff -ru /usr /nyancat/friday/usr
    5. Corrupt it again:
      dd if=/dev/zero of=/dev/vdd bs=1024k count=2000 seek=50
    6. Unmount the ZFS filesystems and export (stop using) the zpool:
      zfs umount -a
      zpool export -a
      zpool status
    7. “Import” the pool, mount the filesystems, and note that the checksum error count is back to zero (it counts since the last mount not for all time – unlike BTRFS):
      zpool import -a
      zfs mount -a
      zpool status
    8. Check that the data is still intact and look for increases in the error count:
      zpool status
      diff -ru /usr /nyancat/friday/usr
      zpool status
    1. Offline corruption

    2. Umount the filesystem and corrupt the start of one device:
      zfs umount -a
      zpool export -a
      dd if=/dev/zero of=/dev/vdd bs=1024k count=200
    3. Try mounting it again which will work even though one block device is unavailable:
      zpool import -a
      zpool status
    4. Replace the missing device, look for the device name in the “zpool status” output to replace “123456789” in the following sample command:
      zpool replace -f nyancat 123456789 /dev/vdd
    5. Check that everything is ok:
      zpool status
      diff -ru /usr /nyancat/friday/usr

BTRFS Training Exercises

In 2015 I ran a training session on BTRFS and ZFS. Here are the notes for BTRFS updated for the latest versions of everything when running on KVM. You can do all the same exercises on a non virtual machine, but it’s safest not to do this on a machine with important data. For the KVM setup I use /dev/vdc and /dev/vdd are the devices for test data.

On a Debian Buster or Bullseye system all that you need to do to get ready for this is to install the btrfs-progs package.

  1. Making the filesystem
    1. Make the filesystem, this makes a filesystem that spans 2 devices (note you must use the-f option if there was already a filesystem on those devices):
      mkfs.btrfs /dev/vdc /dev/vdd
    2. Use file(1) to see basic data from the superblocks:
      file -s /dev/vdc /dev/vdd
    3. Mount the filesystem (can mount either block device, the kernel knows they belong together):
      mount /dev/vdd /mnt/tmp
    4. See a BTRFS df of the filesystem, shows what type of RAID is used (note the use of “single” IE RAID-0 for data):
      btrfs filesystem df /mnt/tmp
    5. See more information about FS device use:
      btrfs filesystem show /mnt/tmp
    6. Balance the filesystem to change it to RAID-1 and verify the change, note that some parts of the filesystem were single and RAID-0 before this change):
      btrfs balance start -dconvert=raid1 -mconvert=raid1 -sconvert=raid1 --force /mnt/tmp
      btrfs filesystem df /mnt/tmp
    7. See if there are any errors, shouldn’t be any (yet):
      btrfs device stats /mnt/tmp
    8. Copy some files to the filesystem:
      cp -r /usr /mnt/tmp
    9. Check the filesystem for basic consistency (only checks checksums):
      btrfs scrub start -B -d /mnt/tmp
  2. Online corruption
    1. Corrupt the filesystem:
      dd if=/dev/zero of=/dev/vdd bs=1024k count=2000 seek=50
    2. Scrub again, should give a warning about errors:
      btrfs scrub start -B /mnt/tmp
    3. Check error count:
      btrfs device stats /mnt/tmp
      dmesg
    4. Corrupt it again:
      dd if=/dev/zero of=/dev/vdd bs=1024k count=2000 seek=50
    5. Unmount it:
      umount /mnt/tmp
    6. In another terminal follow the kernel log:
      tail -f /var/log/kern.log
    7. Mount it again and observe it reporting (and maybe correcting) errors on mount:
      mount /dev/vdd /mnt/tmp
    8. Run a diff, observe kernel error messages and observe that diff reports no file differences:
      diff -ru /usr /mnt/tmp/usr/
    9. Run another diff, you probably won’t observe kernel error messages as all errors in data read by diff were probably fixed in the previous run. Observe that diff reports no file differences:
      diff -ru /usr /mnt/tmp/usr/
    10. Run another scrub, this may correct some errors which weren’t discovered by diff:
      btrfs scrub start -B -d /mnt/tmp
  3. Offline corruption
    1. Umount the filesystem, corrupt the start, then try mounting it again which will fail because the superblocks were wiped:
      umount /mnt/tmp
      dd if=/dev/zero of=/dev/vdd bs=1024k count=200
      mount /dev/vdd /mnt/tmp
      mount /dev/vdc /mnt/tmp
    2. Note that the filesystem was not mountable due to a lack of a superblock. It might be possible to recover from this but that’s more advanced so we will restore the RAID.
      Mount the filesystem in a degraded RAID mode, this allows full operation.
      mount /dev/vdc /mnt/tmp -o degraded
    3. Add /dev/vdd back to the RAID:
      btrfs device add /dev/vdd /mnt/tmp
    4. Show the filesystem devices, observe that vdd is listed twice, the missing device and the one that was just added:
      btrfs filesystem show /mnt/tmp
    5. Remove the missing device and observe the change:
      btrfs device delete missing /mnt/tmp
      btrfs filesystem show /mnt/tmp
    6. Balance the filesystem, not sure this is necessary but it’s good practice to do it when in doubt:
      btrfs balance start /mnt/tmp
    7. Umount and mount it, note that the degraded option is not needed:
      umount /mnt/tmp
      mount /dev/vdc /mnt/tmp
  4. Compression
    1. Get the properties of the root of the btrfs filesystem, set it to zstd compression (which is inherited when creating subdirectories) and inspect the change:
      btrfs property get /mnt/tmp
      btrfs property set /mnt/tmp compression zstd
      btrfs property get /mnt/tmp
    2. View the space used, convert the filesystem to zstd compression, and view the new space used:
      df -h /mnt/tmp
      btrfs filesystem defrag -czstd -r /mnt/tmp
      df -h /mnt/tmp

  5. Experiment
    1. Experiment with the “btrfs subvolume create” and “btrfs subvolume delete” commands (which act like mkdir and rmdir).
    2. Experiment with “btrfs subvolume snapshot SOURCE DEST” and “btrfs subvolume snapshot -r SOURCE DEST” for creating regular and read-only snapshots of other subvolumes (including the root).