From b5608ab92a4f8a5140571acabf54e3c6bdebd0e4 Mon Sep 17 00:00:00 2001 From: Prefetch Date: Wed, 24 Feb 2021 09:47:22 +0100 Subject: Initial commit --- .gitignore | 1 + Makefile | 10 + archetypes/default.md | 7 + archetypes/default.pdc | 9 + config.toml | 5 + content/_index.md | 17 + content/blog/2020/email-server-extras.md | 414 ++++++++++++ content/blog/2020/email-server.md | 718 +++++++++++++++++++++ content/blog/_index.md | 7 + content/know/_index.md | 32 + content/know/category/_index.md | 8 + content/know/category/mathematics.md | 9 + content/know/category/physics.md | 9 + content/know/category/quantum-mechanics.md | 9 + content/know/concept/_index.md | 8 + content/know/concept/blochs-theorem/index.pdc | 115 ++++ content/know/concept/convolution-theorem/index.pdc | 100 +++ .../know/concept/dirac-delta-function/index.pdc | 109 ++++ content/know/concept/dirac-notation/index.pdc | 129 ++++ content/know/concept/fourier-transform/index.pdc | 117 ++++ content/know/concept/gram-schmidt-method/index.pdc | 47 ++ content/know/concept/hilbert-space/index.pdc | 202 ++++++ content/know/concept/legendre-transform/index.pdc | 89 +++ content/know/concept/parsevals-theorem/index.pdc | 76 +++ .../partial-fraction-decomposition/index.pdc | 60 ++ .../concept/pauli-exclusion-principle/index.pdc | 125 ++++ content/know/concept/probability-current/index.pdc | 98 +++ content/know/concept/slater-determinant/index.pdc | 54 ++ .../know/concept/sturm-liouville-theory/index.pdc | 346 ++++++++++ .../time-independent-perturbation-theory/index.pdc | 329 ++++++++++ .../index.pdc | 198 ++++++ content/uses.md | 110 ++++ layouts/_default/single.html | 12 + layouts/blog/list.html | 25 + layouts/blog/single.html | 14 + layouts/home.html | 13 + layouts/know/category.html | 36 ++ layouts/know/know-list.html | 32 + layouts/know/know.html | 12 + layouts/know/single.html | 13 + layouts/partials/footer.html | 7 + layouts/partials/head.html | 3 + layouts/partials/mathjax.html | 1 + layouts/partials/navigation.html | 9 + static/logo256x256.gif | Bin 0 -> 2061 bytes static/logo96x64.gif | Bin 0 -> 467 bytes static/main.css | 25 + static/mathjax.js | 1 + 48 files changed, 3770 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 archetypes/default.md create mode 100644 archetypes/default.pdc create mode 100644 config.toml create mode 100644 content/_index.md create mode 100644 content/blog/2020/email-server-extras.md create mode 100644 content/blog/2020/email-server.md create mode 100644 content/blog/_index.md create mode 100644 content/know/_index.md create mode 100644 content/know/category/_index.md create mode 100644 content/know/category/mathematics.md create mode 100644 content/know/category/physics.md create mode 100644 content/know/category/quantum-mechanics.md create mode 100644 content/know/concept/_index.md create mode 100644 content/know/concept/blochs-theorem/index.pdc create mode 100644 content/know/concept/convolution-theorem/index.pdc create mode 100644 content/know/concept/dirac-delta-function/index.pdc create mode 100644 content/know/concept/dirac-notation/index.pdc create mode 100644 content/know/concept/fourier-transform/index.pdc create mode 100644 content/know/concept/gram-schmidt-method/index.pdc create mode 100644 content/know/concept/hilbert-space/index.pdc create mode 100644 content/know/concept/legendre-transform/index.pdc create mode 100644 content/know/concept/parsevals-theorem/index.pdc create mode 100644 content/know/concept/partial-fraction-decomposition/index.pdc create mode 100644 content/know/concept/pauli-exclusion-principle/index.pdc create mode 100644 content/know/concept/probability-current/index.pdc create mode 100644 content/know/concept/slater-determinant/index.pdc create mode 100644 content/know/concept/sturm-liouville-theory/index.pdc create mode 100644 content/know/concept/time-independent-perturbation-theory/index.pdc create mode 100644 content/know/concept/wentzel-kramers-brillouin-approximation/index.pdc create mode 100644 content/uses.md create mode 100644 layouts/_default/single.html create mode 100644 layouts/blog/list.html create mode 100644 layouts/blog/single.html create mode 100644 layouts/home.html create mode 100644 layouts/know/category.html create mode 100644 layouts/know/know-list.html create mode 100644 layouts/know/know.html create mode 100644 layouts/know/single.html create mode 100644 layouts/partials/footer.html create mode 100644 layouts/partials/head.html create mode 100644 layouts/partials/mathjax.html create mode 100644 layouts/partials/navigation.html create mode 100644 static/logo256x256.gif create mode 100644 static/logo96x64.gif create mode 100644 static/main.css create mode 100644 static/mathjax.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6a2fe92 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/public/* diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..104b8ff --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +FINDARGS= \( -name "*.html" -o -name "*.xml" -o -name "*.css" -o -name "*.js" \) + +all: + rm -rf public/* + hugo + for f in `find public/ -type f $(FINDARGS)`; do \ + echo "Compressing $$f..." ; \ + gzip --keep --force -9 $$f ; \ + brotli --keep --force -Z $$f ; \ + done diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 0000000..555c1bd --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,7 @@ +--- +title: "{{ replace .Name "-" " " | humanize }}" +firstLetter: "{{ slicestr .Name 0 1 | upper }}" +date: {{ .Date }} +draft: false +--- + diff --git a/archetypes/default.pdc b/archetypes/default.pdc new file mode 100644 index 0000000..031a41e --- /dev/null +++ b/archetypes/default.pdc @@ -0,0 +1,9 @@ +--- +title: "{{ replace .Name "-" " " | humanize }}" +firstLetter: "{{ slicestr .Name 0 1 | upper }}" +publishDate: nil +date: {{ .Date }} +draft: false +markup: pandoc +--- + diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..d5a8d6d --- /dev/null +++ b/config.toml @@ -0,0 +1,5 @@ +baseURL = "" +languageCode = "en-us" +title = "Prefetch" + +disableKinds = ["taxonomy", "term"] diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000..e9e5dcc --- /dev/null +++ b/content/_index.md @@ -0,0 +1,17 @@ +--- +title: "Home" +date: 2021-02-22T17:15:50+01:00 +draft: false +--- + +Welcome to my website. + +Once in a blue moon, I'll post something here +related to my areas of interest: +programming, optimization, +mathematics, physics and even linguistics. + +This site is served to you by [nginx](https://nginx.org/), +and statically generated by [Hugo](https://gohugo.io). +I intend to keep it forever free of advertising and trackers, +and to maintain my A+ score for [TLS quality](https://www.ssllabs.com/ssltest/analyze.html?d=prefetch.eu). diff --git a/content/blog/2020/email-server-extras.md b/content/blog/2020/email-server-extras.md new file mode 100644 index 0000000..72299c9 --- /dev/null +++ b/content/blog/2020/email-server-extras.md @@ -0,0 +1,414 @@ +--- +title: "Setting up an email server in 2020 with OpenSMTPD and Dovecot: extras" +publishDate: 2020-04-27 +date: 2021-02-22T17:19:49+01:00 +draft: false +--- + +# + +This sequel to my earlier [guide](/blog/2020/email-server/) discusses +extra tips and tricks to extend your email setup. +This page will be updated continuously as I come up with ideas. + +Last updated 2020-04-29. + + +## General + +### Multiple domains + +You can generalize your setup to handle multiple domains +with very little effort. In the following, +I'll assume that your two domains are called `foo.com` and `bar.com`. + + +#### DNS records + +There should be MX, SPF, DKIM and DMARC records for both domains, +as explained in the previous guide. Fortunately, these records +can have identical contents for both domains! + +However, it remains essential that the mail server's mailname +and reverse DNS domain name match up exactly, +so you should create MX records with that in mind. +Therefore, if the email server for both domains has `mx1.foo.com` +as reverse DNS name, the MX records should look like this: +```sh +foo.com. MX 42 mx1.foo.com. +bar.com. MX 42 mx1.foo.com. +``` +This is perfectly valid: the only thing that matters is that +what your SMTP server calls itself agrees with what reverse DNS +says that the server is actually called. + + +#### Dovecot + +To make Dovecot aware of multiple domains, +you only need to update the `/etc/dovecot/users` file +to add accounts for both domains. +However, in the original guide, I said to only write `user` +in the file, without the `@foo.com`, for an address `user@foo.com`. +Unsurprisingly, that isn't an option for multiple domains, +so you must put the full address in `/etc/dovecot/users`. + +Then update `/etc/dovecot/dovecot.conf` to reflect that, +by changing `%n` to `%u` in `username_format`: +```sh +userdb { + driver = passwd-file + args = username_format=%u /etc/dovecot/users + override_fields = uid=vmail gid=vmail home=/home/vmail/%d/%n +} +``` +Also note the change in the `home` setting: +the inbox of a user `user@foo.com` will now be stored +in `/home/vmail/foo.com/user`. +That's all you need to change. + + +#### OpenSMTPD + +To inform OpenSMTPD of all the domains, +create a new file `/etc/smtpd/domains`, +and in there put all desired names on their own line: +```sh +foo.com +bar.com +``` +And as I mentioned when discussing the DNS records, +you should check that `/etc/smtpd/mailname` agrees +with your server's reverse DNS. + +Then, in the main configuration file, tell OpenSMTPD to +use the new domains file when deciding whether to accept an message, +by declaring a new table and changing the `match` line for inbound mail: +```sh +table domains "/etc/smtpd/domains" +# ... +match from any for domain action "RECV" +``` + +#### Rspamd + +The last thing to do is to inform Rspamd of the multiple domains. +It's really easy: simply add multiple domain blocks: +```c +domain { + foo.com { + path = "/path/to/dkim/private.key"; + selector = "hello"; + } +} +domain { + bar.com { + path = "/path/to/dkim/private.key"; + selector = "world"; + } +} +``` + +### Advanced security + +SPF, DKIM and DMARC are email's traditional DNS-based security systems, +but in 2018 the IETF released [RFC 8460](https://tools.ietf.org/html/rfc8460) and [RFC 8461](https://www.rfc-editor.org/rfc/rfc8461.txt), +which respectively define TLSRPT and MTA-STS, +two fancy new systems focused on TLS-encrypted email transport. + +These security mechanisms are pretty new, +so you won't get a huge benefit from enabling them, +but big email providers' draconian spam filters might like it. + + +#### TLSRPT + +TLS reporting, or TLSRPT for short, is very simple: +all it does is provide a contact email address in case +somebody has trouble with the TLS configuration of your SMTP server. + +To enable it for your custom email domain `example.com`, +simply create a DNS TXT record for the `_smtp._tls` subdomain: +```sh +_smtp._tls.example.com. TXT "v=TLSRPTv1; rua=mailto:" +``` +Where `` is an email address of your choosing. +That's all! + + +#### MTA-STS + +MTA Strict Transport Security (MTA-STS) tells other servers +that you take TLS encryption of messages very seriously, +so they should avoid sending you unencrypted email, +and should only accept certain certificates from your side. + +Compared to the previously discussed DNS-based security extensions, +MTA-STS is a bit more work to set up, +because you'll also need an HTTP web server. + +The DNS part is still pretty simple: +create yet another DNS TXT record, +this time for the subdomain `_mta-sts`: +```sh +_mta-sts.example.com. TXT "v=STSv1; id=" +``` +The `` should identify the version of your policy, +so other servers can quickly see if something changed. +I recommend using today's date. + +For the next part, I'll assume that you already have +a web server running on a server with the IP address `1.2.3.4`. +I use [nginx](https://nginx.org/) for this, running +on the same server as OpenSMTPD and Dovecot, +but you don't have to do the same. + +Create an A record which binds your server +to the subdomain `mta-sts` (without underscore): +```sh +mta-sts.example.com. A 1.2.3.4 +``` +Set your web server to serve the file +`https://mta-sts.example.com/.well-known/mta-sts.txt` +(we'll discuss that file in a moment). +Note that this policy file **must** be served over HTTPS, +so you need a valid TLS certificate for that domain. + +The contents of the `mta-sts.txt` policy file are as follows, +where `mx1.example.com` and `mx2.example.com` are the hosts +mentioned in `example.com`'s DNS MX records: +```sh +version: STSv1 +mode: enforce +mx: mx1.example.com +mx: mx2.example.com +max_age: +``` +All MX servers must be mentioned this way. +If you're feeling cautious, you may want to set +`mode` to `testing` in the beginning. +This policy is valid for `` seconds, +which is recommended to be several weeks, +but to start with, I suggest using 86400 seconds (one day). +Finally, ensure that this file has CRLF Windows-style line endings. + +To correctly pass an MTA-STS test, the TLS certificate +presented by e.g. `mx1.example.com` should be valid for `mx1.exaple.com`. +To achieve this without needing to manage too many certificates, +you can specify multiple domains when requesting a certificate, +or you can use a wildcard domain (`*.example.com`). +Note, however, that MTA-STS testing tools don't like +the latter option, so I recommend the former. + +Once you're done, check your work by using either +[ESMTP](https://esmtp.email/tools/mta-sts/)'s or [Ayke](https://aykevl.nl/apps/mta-sts/)'s +online MTA-STS validation tools, +ignoring any warnings about DNSSEC or DANE. +If all is good, great! + +Even if you did everything correctly, +these tools will warn you that you're not using DNSSEC/DANE. +It might then be tempting to set that up for even more security, +but I recommend against that for private servers: take a look at [this](https://dane.sys4.de/common_mistakes). + + + +## OpenSMTPD + +### Client certificates (in addition to passwords) + +You can configure OpenSMTPD to request a client certificate +for sending emails, as a second factor for authentication. + + +#### Certificates + +We need to start with some cryptography to create and verify certificates. +I recommend that you do all of this on your trusted *client* device, +and only copy the necessary files to the server later. + +DISCLAIMER: +All the keys and certificates that we'll generate in this section are +for **private use** only, to handle a small number of trusted clients. +I'm not a cryptography expert, so you should **not** listen to me +for large-scale systems that may involve untrusted devices. + +The first step is to set up a private Certificate Authority (CA), +which issues the client certificates and can be used to verify them. +Start by generating an RSA private key, +which you should store in a safe place and not share with anyone: +```sh +$ openssl genrsa -out mailca.key 2048 +``` +Extract a public certificate from this key as follows. +Because we're lazy, we give it a lifetime of 36500 days: +```sh +$ openssl req -new -x509 -days 36500 -key mailca.key -out mailca.crt +``` +When running this command, OpenSSL will ask you some questions +about who this certificate is intended for. +Since this is for personal use, your answers don't matter, +so just use the defaults. +Some fields (I think only *Country Name* and *Organization Name*) +cannot be empty, but the others can. + +Moving on to the client, once again generate an RSA private key: +```sh +$ openssl genrsa -out mailclient.key 2048 +``` +From this private key, create a Certificate Signing Request (CSR) +as follows, where you'll be asked the same questions as before: +```sh +$ openssl req -new -key mailclient.key -out mailclient.csr +``` +By feeding this CSR to the CA, we can create a signed client certificate +that can be verified using the CA's public certificate. +```sh +$ openssl x509 -req -in mailclient.csr -out mailclient.crt \ + -days 36499 -CA mailca.crt -CAkey mailca.key +``` +If you want to multiple client certificates, +just repeat the last few steps for each one. + + +#### Server + +OpenSMTPD needs to verify the validity of client certificates +using the CA's public certificate, so you should copy that +to somewhere on the server, e.g. `/etc/smtpd/mailca.crt`, +and declare it to OpenSMTPD by adding this near +the top of `/etc/smtpd/smtpd.conf`: +```sh +ca "mailca" cert "/etc/smtpd/mailca.crt" +``` +Then replace the entire configuration for outbound mail as follows. +Note that this removes SMTPS support, leaving only STARTTLS: +```sh +# Outbound +listen on eth0 port 587 tls-require verify pki "example.com" ca "mailca" auth filter "rspamd" +action "SEND" relay srs +match from any auth for any action "SEND" +``` +The magic word here is "`verify`", which tells OpenSMTPD +to ask for a client certificate and to verify it using the given CA. + + +#### Client + +Now you won't be able to send emails if your client doesn't +present its certificate to the server! +Unfortunately, not all mail clients support this; personally +I use [Thunderbird](https://www.thunderbird.net/) with success. +I won't include any client-specific configuration here, +but I will say this: + +For some clients (like Thunderbird), you'll have an easier time +importing your client certificate if you encode it in the +[PKCS #12](https://en.wikipedia.org/wiki/PKCS_12) storage format: +```sh +$ openssl pkcs12 -export -in mailclient.crt -inkey mailclient.key \ + -certfile mailca.crt -out mailclient.pfx +``` +OpenSSL will ask you to set a password, which you'll need to +enter again when importing the certificate into the client. + + + +### Client certificates (instead of passwords) + +If you really want to, you can use the client certificates +as a substitute for passwords. This is especially useful +if you set up a catchall inbox in Dovecot, +because this will allow you to send emails +from arbitrary addresses from your domain. + +To do this, follow the same procedure as in the previous section, +but with a slightly different OpenSMTPD configuration: +```sh +listen on eth0 port 587 tls-require verify pki "example.com" ca "mailca" filter "rspamd" tag "VALID" +action "SEND" relay srs +match from any tag "VALID" for any action "SEND" +``` +All incoming connections that present a good certificate +will be tagged as being `VALID`, and their mail will be relayed. + +Unfortunately, we're not quite done yet here, +because Rspamd is now very confused... + + +#### Rspamd + +When OpenSMTPD passes a message through Rspamd, it also includes +some metadata, most notably whether the sender has authenticated +successfully with OpenSMTPD... which is now no longer the case +for submissions, because we've removed the `auth` directive! + +Rspamd therefore starts regarding these outgoing emails +as *incoming* emails, because they don't seem +to come from a trusted user. So instead of signing them with DKIM +and handing them back to OpenSMTPD, it will do a full spam scan. +If they get a high spam score (which is likely for short test emails), +*your* spam filter, running on *your* server, +will be flagging *your* messages as spam! + +The solution is to whitelist your domain(s) in Rspamd, +so it won't scan them. To do this, create a new file +`/etc/rspamd/local.d/settings.conf` with these contents, +where `foo.com` and `bar.com` are the domains to whitelist: +```c +outbound { + priority = high; + from = "@foo.com"; + from = "@bar.com"; + apply { + actions { + add_header = 1000; + } + } +} +``` +Setting `priority` to `high` ensures that Rspamd checks +this rule before doing anything else. +You can add any number of `from` directives; +this rule will be applied if any of them match. +It only sets the threshold for the action `add_header` to `1000`. +That is, if the email doesn't get a spam score of at least 1000 +(the default is 6) Rspamd will not add any spam tags. + +Because Rspamd is still regarding your emails as inbound, +you also need to change the global settings of +the DKIM signer in `/etc/rspamd/local.d/dkim_signing.conf`, +such that they include the following: +```c +sign_inbound = true; +allow_hdrfrom_mismatch = true; +allow_username_mismatch = true; +``` +This tells Rspamd to add DKIM signatures to incoming emails, +which in this case includes yours. +Allowing these mismatches ensures that the messages still get signed, +even if you're sending from an arbitrary address. + + + +## Dovecot + +### Catchall inbox + +In Dovecot, you can create a catch-all inbox that will accept all +emails sent to your domain that don't match anyone in `/etc/dovecot/users`. +Just add another `userdb` block *after* the first: +```sh +userdb { + driver = static + args = uid=vmail gid=vmail home=/var/vmail/catchall allow_all_users=yes +} +``` +The `static` driver means there is no table file: +all configuration is directly within this `userdb` block. +If we don't specify `allow_all_users=yes`, then Dovecot +will check whether users exist using the `passdb` table, +and will conclude that the recipient is invalid. + + + diff --git a/content/blog/2020/email-server.md b/content/blog/2020/email-server.md new file mode 100644 index 0000000..3b7f439 --- /dev/null +++ b/content/blog/2020/email-server.md @@ -0,0 +1,718 @@ +--- +title: "Setting up an email server in 2020 with OpenSMTPD and Dovecot" +publishDate: 2020-04-27 +date: 2021-02-22T17:27:49+01:00 +draft: false +--- + +# + +So, you want to set up your own email server? In that case, welcome. + +There are many reasons to run a custom email server, +ranging from privacy concerns about providers like Google, +to just wanting to do it for fun and/or learning. +Since you're here, I assume you've already found a reason. + +Beware: this is a messy topic, and the available documentation +is even messier, so it could take a while before you get it to work properly. +I've compiled this guide according to my experiences +in an attempt to make this dark art more accessible, +but your mileage may vary considerably. I hope you find it useful. + +This guide is aimed at people who are comfortable with +the Linux/*BSD command line. + +When you're done, take a look at the +[sequel](/blog/2020/email-server-extras/) +for ideas to extend your setup. + +Last content update on 2020-04-29. Last correction on 2021-02-20. + + + +## Preparation + +Setting up email is relatively complex compared to e.g. a static website, +because you need to configure not one, but *two* server programs, +*and* you need to shoehorn modern security features into email's Stone-Age design. +I'll start by explaining the general structure of a mail server setup. + + +### How email works + +The programs involved in the exchange of emails are called [agents](https://en.wikipedia.org/wiki/Email_agent_(infrastructure)). +Officially, there are 5 different types of agent: MUA, MSA, MTA, MDA and MRA. +But fortunately, it's reasonable to treat the MRA and MSA +as being part of the MUA and MTA, respectively. + +The *Mail User Agent* (MUA) is simply the client on your device at home +that you use to send and receive emails, and this guide assumes +you already have a favourite program for this, e.g. [Thunderbird](https://www.thunderbird.net/en-US/). +Nowadays it's fashionable to use a web interface for emails, +but that's also beyond the scope of this guide. + +The *Mail Delivery Agent* (MDA) is a program that watches over +the server's copy of your mailbox: it manages your inbox, +remembers which messages you have or haven't read, +keeps a copy of your drafts, etc. +When you open your mailbox, your MUA will connect to +your server's MDA using the [IMAP](https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol) protocol +(or [POP3](https://en.wikipedia.org/wiki/Post_Office_Protocol), but that one's [obsolete](https://pop2imap.com/)). + +The *Mail Transfer Agent* (MTA) is responsible for +making messages arrive at the right destination. +When you send an email, your MUA will pass it on to your server's MTA, +which will in turn pass it on to the recipient's mail server. +Likewise, when someone sends *you* an email from another server, +the MTA will receive it and hand it over to the MDA so you can read it later. +In both cases the MTA speaks the [SMTP](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol) protocol. + +In this guide our MDA will be [Dovecot](https://dovecot.org/), +which is a very popular choice for that role. +As for the MTA, there exist several options, +the most popular being [Postfix](http://www.postfix.org/) and [Exim](https://exim.org/). +However, this guide uses the newer, lesser-known [OpenSMTPD](https://opensmtpd.org/), +which in my experience is *much* easier to set up: +Postfix and Exim have complex configurations and +are geared towards large-scale email providers, +whereas OpenSMTPD is more beginner-friendly. + + + +### Security + +The base email system is horribly insecure on its own, +so we still need to duct-tape on some security features. +In this context, "security" has two meanings: +spam protecion and privacy protection (encryption). + +Spam protection also means two things here: +defending yourself against spammers, and +preventing that *your* emails get flagged as spam. +The former is optional, but the latter is not: +big providers such as Google and Microsoft +use infamously strict spam filters, +and if they decide that your server is a spammer, +there's almost nothing you can do about it. +Spam protection techniques will be discussed +in more detail over the course of this guide. + +Privacy protection is important in the 21st century: +you don't want a random router in the Internet to read all your emails, +which may contain sensitive information such as +private conversations and account password reset links. +You should therefore try to make sure that emails are +transported over an encrypted channel. +To do this, you have two options for encryption: +*mandatory* and *opportunistic* encryption. + +Mandatory encryption is only practical for client-server +communication (not server-server), and is provided by IMAPS and SMTPS, +which wrap the IMAP and SMTP protocols in [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security), +in the same way that [HTTPS](https://en.wikipedia.org/wiki/HTTPS) does for [HTTP](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol). + +For server-server communication, the only option is +opportunistic encryption in the form of [STARTTLS](https://en.wikipedia.org/wiki/STARTTLS), +where communication is only encrypted if both parties agree +after a short unencrypted discussion. +That last part is vulnerable to [MitM](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) attacks, +where anyone along the path of the email servers' discussion +can alter the exchange to block the use of encryption, +which sometimes actually [happens](https://www.eff.org/deeplinks/2014/11/starttls-downgrade-attacks) in practice. + +The only way to make sure that STARTTLS is used in that case +is to refuse any exchange unless the servers agree to use encryption. +Unfortunately, that's a risky approach that I can't recommend, +because not all servers support encryption (unbelievable, right?). +For example, I've received airline booking confirmations, +full of personal details, and made with billion-dollar companies, +sent across the Internet without any protection. + +This guide includes intructions to enable encryption, +but assumes that you already have a TLS certificate for that. +If not, find a guide to get one from [Let's Encrypt](https://letsencrypt.org/) (it's free!), +and remember that you'll need to renew it every few months. +Using a self-signed certificate *may* work, but I don't recommend it. + +In the rest of this guide I'll assume that +you have a public full-chain TLS certificate at `/etc/ssl/certs/example.com.pem`, +and a private encryption key at `/etc/ssl/private/example.com.pem`. + + + +### Server + +Obviously, you'll need a server to run the MTA and MDA on. +You can host your own at home, but the more reliable option is +to rent one in a data center ([VPS](https://en.wikipedia.org/wiki/Virtual_private_server)). +This guide was written with a Linux server in mind, +but in theory it should also work on the BSDs +([OpenBSD](https://www.openbsd.org/), [FreeBSD](https://www.freebsd.org/), +[NetBSD](https://www.netbsd.org/), etc.) with minimal adaptation. + +The server must be online 24/7, you must have root SSH access, +it must have a static IP address, and TCP network port 25 must be open. +Especially check that last one: you may need to explicitly ask +your home ISP or the server provider to enable port 25, +because they often close it to prevent spam. +You can usually do this from their web interface. + +You also must have a domain name, which I'll call `example.com`. +This will be necessary for basically everything: +DNS records, TLS certificate, MTA network configuration, etc. +If you don't have one yet, you can choose between many registrars +to rent one from. Personally I use and can recommend [Gandi](https://www.gandi.net/). + +Note that it's a **bad** idea to use a domain like `foo.bar.com`, +where you control the `foo` part but *not* the `bar` part: +in that case, a spammer in control of `qux.bar.com` +could negatively affect *your* reputation +in the eyes of other email providers. + +Lastly, when setting up an email server, you also have the choice +between using to *system* users or *virtual* users. +With system users, if an email arrives for `john@example.com`, +then the MTA and MDA will expect that there exists +a `john` Unix user on the server to deliver it to. +With virtual users, you have much more flexibility, so that's what we'll use. +All email will be managed under a single Unix user/group called `vmail`. +Create it as follows: +```sh +# GNU CoreUtils: +$ groupadd vmail +$ useradd -g vmail vmail +# BusyBox: +$ addgroup vmail +$ adduser -D -G vmail vmail +# *BSD: +$ no clue, but it should be similar +``` + + +## DNS records + +Now we must set up all the necessary DNS records, which +is usually possible from the domain registrar's web interface. +It may take a while for your changes to propagate over the Internet, +so I recommend doing this section now and the rest tomorrow. + +Firstly, you should already have an A and/or AAAA record +to associate your domain `example.com` with the server's IP address. +For email it is **essential** that you also have [reverse DNS](https://en.wikipedia.org/wiki/Reverse_DNS_lookup) +set up correctly. If you're renting your server remotely, +you can often do this from the provider's configuration tool, +otherwise, you should create a PTR-type DNS record, +although that's beyond the scope of this guide. + +Once you're done, I recommend testing your DNS records +using the [MX Lookup](https://mxtoolbox.com/MXLookup.aspx) online tool. + + + +### MX + +To inform the rest of the Internet that your server is an email server, +create an MX (Mail eXchanger) DNS record for your domain. +Note the dot at the end of the domain name: +``` +example.com. MX 42 example.com. +``` +When a message is sent to an email address ending in `@example.com`, +the sender will query DNS for any MX records for `example.com`. +There it will find a domain name (in this case `example.com` again), +for which it will look up the IP address using an A/AAAA record. +The domain name in the record must **not** have an associated CNAME record; +it must be directly translatable to an IP address. + +You may have multiple MX records, containing different domain names, +each with a preference number (`42` in the example above). +The sender will try MX records with *lower* numbers first, +and if that server is unavailable, it will try a higher number. +If you have multiple mail servers (which is a good idea), +you can thus declare those as follows: +``` +example.com. MX 13 mx1.example.com. +example.com. MX 42 mx2.example.com. +``` +Here, a server sending an email to your domain `example.com` +will try to send it to the IP address of `mx1.example.com` first, +and if that fails, it will move on to `mx2.example.com`. +If both `mx1` and `mx2` have the same number, then the sender +will randomly choose one, which is useful for load balancing, +although that's probably overkill for a private server. + + + +### SPF + +The [Sender Policy Framework](https://en.wikipedia.org/wiki/Sender_Policy_Framework) (SPF), +is a feature which helps prevent spammers from impersonating +your server in an attempt to get around blacklists. +This security feature is **required** nowadays: +if you don't use it, you'll probably get flagged as spam. + +SPF works by specifying which IP addresses are authorized +to send emails from your domain name. +You must publish this information in a +TXT-type DNS record (**not** SPF-type, which also exists!) with the following contents: +``` +example.com. TXT "v=spf1 mx -all" +``` +Everything after the version `v=spf1` is a list of *verification mechanisms* +for a spam filter to try out in the given order. +The `-all` at the end says to reject your email +if all of the previous mechanisms fail. +See the [SPF spec](https://tools.ietf.org/html/rfc7208) for details. + +I recommend only using the `mx` mechanism, which tells the verifier +to look at the A/AAAA addresses of the domains in your MX records. +This allows you to add, remove, or change your servers +without needing to update this record. + + + +### DKIM + +Then we have [DomainKeys Identified Mail](https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail) (DKIM), +which is a more comprehensive form of anti-impersonation, +and, like SPF, is practically **mandatory** in the modern era. + +It adds a cryptographic signature to all emails from your server, +which the receiver's spam filter will verify using the email's contents, +and a public key that you need to publish in a DNS record. +Again, you should implement *both* SPF and DKIM, despite their overlap. + +To set up DKIM, create an RSA keypair, using the `openssl` utility: +```sh +$ openssl genrsa -out /path/to/dkim/private.key 2048 +$ openssl rsa -in /path/to/dkim/private.key -out /path/to/dkim/public.key +``` +The minimum size is 1024 bits, but I recommend 2048 bits. +Bigger is better, but because DNS is involved you can't stretch it +to 4096 bits without causing discomfort to [some](https://serverfault.com/questions/747185/dkim-can-i-use-a-rsa-key-larger-than-2048bit-i-e-4096) servers. +And I think it goes without saying that you should keep the private key private. + +Importantly, the DKIM DNS record **cannot** be +attached directly to your domain `example.com`; +instead, it should belong to a subdomain of the form +`._domainkey.example.com`, +where `` is an alphanumeric string you can choose (e.g. today's date), +just remember your choice for later when configuring the DKIM signer. +And if you change your key, keep the old record around +for a while so old emails can still be verified. + +Your DKIM policy must be published in a TXT record +as follows, where `` is the public RSA key `MI...AB` +stored in `/path/to/dkim/public.key`, with the newlines removed: +``` +._domainkey.example.com. TXT "v=DKIM1; t=s; h=sha256; p=" +``` +Here, `v=DKIM1` is the version and must be the first tag. +The flag `t=s` enables strict mode, as recommended by the [DKIM spec](https://tools.ietf.org/html/rfc6376), +meaning that emails sent from subdomains immediately fail verification. +The optional tag `h=sha256` blocks the use of the old SHA1 algorithm. + + + +### DMARC + +Lastly, we have [Domain-based Message Authentication, Reporting and Conformance](https://en.wikipedia.org/wiki/DMARC) (DMARC), +which is *technically* optional, but *highly* recommended, +because it will make you look more legitimate in the eyes of Google and Microsoft. +It can modify the behaviour of SPF and DKIM, +and also provides advice about what a receiver should do +if one of your emails fails verification. + +To enable it, create yet another TXT record, which, +similarly to DKIM, **must** belong to the subdomain `_dmarc.example.com`, +and give it the following contents, +where `` is an email address of your choosing, +which may or may not belong to your domain: +``` +_dmarc.example.com. TXT "v=DMARC1; p=reject; sp=reject; pct=100; aspf=s; adkim=s; fo=1; ruf=mailto:" +``` +The version tag `v=DMARC1` must come first, +followed by `p=` and `sp=`, which control what to do to unverified messages +coming from the main domain and subdomains, respectively. +Unsurprisingly, `reject` means that delivery should be refused, +`none` asks to let it through anyway, and `quarantine` tells +the filter to take a closer look or to put it in a spam folder. +The percentage `pct=100` says how many of your emails to apply the policy to. +Next, `aspf=s` and `adkim=s` enable strict mode for both SPF and DKIM, +which blocks subdomains from passing the test. +Finally, `fo=1` asks the filter to create a forensic report +if any type of verification fails, and `ruf=` gives an address to send it to. +If in doubt, see the [DMARC spec](https://tools.ietf.org/html/rfc7489). + + + +## MDA: Dovecot + +[Dovecot](https://www.dovecot.org/) is a very popular IMAP server, +focused on being lightweight, simple, and secure, +and has extensive and up-to-date documentation. +It's very flexible and scalable, and keeps up well +with the lastest security best-practices. + +If you installed Dovecot via a package manager, +you'll probably have lots of configuration files +in the `/etc/dovecot` directory. +I want you to delete all of them. Yes, `rm -rf` that crap. +Dovecot is simple to configure, and doesn't care where +you put its settings, so having all that chaos in `/etc/dovecot` +just makes things unnecessarily confusing. + + + +### Network + +Create a new configuration file `/etc/dovecot/dovecot.conf`, +and start by filling in the details of your TLS certificate, +making clear that unencrypted connections are unacceptable: +```sh +ssl = required +ssl_cert = +``` +Generate the password hash with this command for each user. +Be sure to use the same password for every account as in Dovecot: +```sh +$ smtpctl encrypt '' +``` +Then, like with Dovecot, just delete the contents of +the main config file `/etc/smtpd/smtpd.conf`, +and start by putting in the following: +```sh +table aliases "/etc/smtpd/aliases" +table passwds "/etc/smtpd/passwds" +``` + + +### Network + +Write your domain name on a single line in `/etc/smtpd/mailname`. +This is the name that OpenSMTPD will use to introduce itself +to other servers, and it's important that this matches +the reverse DNS domain name of the server's IP: +```sh +example.com +# Or mx1.example.com or whatever +``` +Then continue in `/etc/smtpd/smtpd.conf` by importing your TLS certificate: +```sh +pki "prefet.ch" cert "/etc/ssl/certs/example.com.pem" +pki "prefet.ch" key "/etc/ssl/private/example.com.key" +``` +And tell OpenSMTPD which keys to use for the [Sender Rewriting Scheme](https://en.wikipedia.org/wiki/Sender_Rewriting_Scheme), +which prevents forwarded emails from breaking SPF and looking like spam: +```sh +srs key "" +srs key backup "" # optional, read below +``` +It's recommended to change the key every year or so, +but in that case you need to ensure that emails from the last month +can still be verified using the old one, so if you change it, +simply move it to the backup slot for a month. + +It's very important that the secrets can't be guessed, +otherwise *anyone* can send mail through your server, +so I recommend generating these keys randomly as follows: +```sh +$ head -c 30 /dev/urandom | base64 +``` +Next, define the spam filters as follows. +For the last line to work, you'll need to [download](https://github.com/poolpOrg/filter-rspamd) +and build the `filter-rspamd` adapter binary for yourself, +created by OpenSMTPD's official maintainer. +We'll set up the Rspamd service in the next section, +which will be responsible for spam filtering and DKIM signing: +```sh +filter "rdns" phase connect match !rdns disconnect "550 DNS error" +filter "fcrdns" phase connect match !fcrdns disconnect "550 DNS error" +filter "rspamd" proc-exec "/etc/smtpd/filter-rspamd" +``` +I cannot overstate the importance of the first two lines: +these will block hundreds of spam attempts, and have, +at least for me, never blocked anything legitimate so far. + +The only thing left to do here is to tell OpenSMTPD which ports to listen on +and what to do with the incoming traffic. +This comes in two parts: first, we listen on port 25 for incoming +messages for your domain coming from other email servers: +```sh +# Inbound +listen on eth0 port 25 tls pki "example.com" filter { "rdns", "fcrdns", "rspamd" } +action "RECV" lmtp "/var/run/dovecot/lmtp" rcpt-to virtual +match from any for domain "example.com" action "RECV" +``` +Line 1 says to listen on `port 25` of interface `eth0`, +providing *optional* `tls` using the certificate for `example.com`, +and passing everything through the three filters definer earlier. +Making TLS mandatory is a **bad** idea here, because not all servers can use TLS. + +Line 2 defines an action called `RECV`, +which relays an email to Dovecot's LMTP socket, +with the `rcpt-to` and `virtual` making sure +that Dovecot will actually accept the message. + +Line 3 then simply says that any incoming mail +for your domain should have the action `RECV` applied to it, +unless the spam filters rejected it. + +Secondly, we listen on port 465 (SMTPS) +and/or port 587 (STARTTLS) for messages getting sent +from your email client to the rest of the world, +so we require user authentication: +```sh +# Outbound +listen on eth0 port 465 smtps pki "example.com" auth filter "rspamd" +listen on eth0 port 587 tls-require pki "example.com" auth filter "rspamd" +action "SEND" relay srs +match from any auth for any action "SEND" +``` +The only difference between lines 1 and 2 is the port and the protocol. +Both demand a mandatory TLS connection, and that users authenticate +themselves according to the password file created earlier. +The `filter` at the end is for DKIM signing of outgoing mail. + +Lines 3 and 4 are only triggered after successful `auth`entication, +and, unsurprisingly, `relay` the email to its destination. +The `srs` at the end enables using the SRS settings from earlier. + +OpenSMTPD is the only program in this setup that needs to handle +untrusted connections, when other MTAs send you messages. +Since, like most server software, it may have [vulnerabilities](https://opensmtpd.org/security.html), +it is **very** important that you keep it as up-to-date as possible. + + + +## Spam filter: Rspamd + +[Rspamd](https://www.rspamd.com/) is a modern spam filtering solution, +with many features that you could spend hours tweaking. +In this guide, however, we'll keep it short, +because we're only really interested in its ability add +our server's DKIM signature to outgoing messages. + +Besides, according to my limited experience, +for small-scale servers spam filtering isn't essential, +as long as you tell OpenSMTPD to check reverse DNS as described above. +However, there are some much more experienced people who disagree with me. + +Basically, for our purposes, don't touch any of Rspamd's default +configuration except for creating/editing the file +`/etc/rspamd/local.d/dkim_signing.conf` with the following contents, +where `` is the DKIM selector you chose in the DNS record: +```sh +allow_username_mismatch = true; + +domain { + example.com { + path = "/path/to/dkim/private.key"; + selector = ""; + } +} +``` +Make sure that the DKIM `private.key` file is +readable (and *only* readable) by `rspamd:rspamd`. +Allowing username mismatches is necessary, +because OpenSMTPD will only tell Rspamd about `username` +while the DKIM signer actually expects `username@example.com`. + +And... that's it! Of course, don't forget to start all the necessary daemons. + + + +## Testing + +Everything is set up now, so it's time to test. Fingers crossed! + +As mentioned earlier, you can check the correctness +of your DNS using the [MX Lookup](https://mxtoolbox.com/MXLookup.aspx) tool. +You can use the same website to test OpenSMTPD +with the [SMTP Diagnostics](https://mxtoolbox.com/diagnostic.aspx) tool. + +All decent email clients include an option to set the server for an email account. +This guide excludes instructions for that, +because it will vary a lot from client to client. +If asked for your login type, choose plain/normal/unencrypted passwords. +Don't worry, the client-server connection is TLS-encrypted, +so nobody will be able to steal it. + +Next, to test sending and receiving messages, +use the aptly-named [Is my email working?](http://ismyemailworking.com/) website. +After that, specifically test that SPF, DKIM an DMARC +are working correctly using the [DKIM validator](https://dkimvalidator.com/). +If everything is good so far, congratulations! + +Now comes the big scary final test: +sending an email to one of the "big guys", Google or Microsoft. +Their spam filters are very strict, so if you get through, great! +Because these companies probably use AI-powered account-aware filters, +you should *not* put anything identifiable in the test email. +For example, if your name is "John Smith", +do *not* put "John" nor "Smith" in the message, +and do *not* send it from an addres like `john.smith@example.com`. + +If something failed, then you have some investigating to do. +Either one of the daemons is misconfigured, or there's a problem +with your domain name and/or DNS records. +Do some research, and you'll get there, don't give up. + +But if everything works, congratulations! +You're now the proud administrator of a private email server. +Have fun with it, and don't forget to update your +TLS certificate and DKIM and SRS keys. + +PS: and please don't spam; you'll ruin it for everyone else. + diff --git a/content/blog/_index.md b/content/blog/_index.md new file mode 100644 index 0000000..3d4ffc2 --- /dev/null +++ b/content/blog/_index.md @@ -0,0 +1,7 @@ +--- +title: "Blog" +date: 2021-02-22T17:38:58+01:00 +draft: false +--- + +Just a bunch of random ramblings. diff --git a/content/know/_index.md b/content/know/_index.md new file mode 100644 index 0000000..41aeef6 --- /dev/null +++ b/content/know/_index.md @@ -0,0 +1,32 @@ +--- +title: "Knowledge base" +date: 2021-02-22T19:57:05+01:00 +draft: false +layout: "know" +--- + + +# Knowledge base + +Welcome to my knowledge base! + +Over the years, I've learned a lot of physics, mathematics, and computing. +These are vast, difficult subjects, and I've spent many hours of my life +trying to make sense of obscure, poorly explained concepts. +To help me remember what I learn, I write notes in LaTeX. + +This knowledge base is based on my notes, and +is freely available to anyone who might need it. +I hope it helps you in your studies or work. +Currently there's isn't much here yet, +but I have over 200 pages of LaTeX waiting to be converted. + +Keep in mind that I'm only human, +so there are probably mistakes in my work. +I take no responsibility for any injuries incurred as a consequence. +If you're doing something important, +you should check things yourself! + +The contents of this knowledge base are found here: +* [List of concepts](/know/concept/) +* [List of categories](/know/category/) diff --git a/content/know/category/_index.md b/content/know/category/_index.md new file mode 100644 index 0000000..b796457 --- /dev/null +++ b/content/know/category/_index.md @@ -0,0 +1,8 @@ +--- +title: "List of categories" +date: 2021-02-22T20:38:58+01:00 +draft: false +layout: "know-list" +--- + +This is an alphabetical list of the categories in this knowledge base. diff --git a/content/know/category/mathematics.md b/content/know/category/mathematics.md new file mode 100644 index 0000000..693252f --- /dev/null +++ b/content/know/category/mathematics.md @@ -0,0 +1,9 @@ +--- +title: "Mathematics" +firstLetter: "M" +date: 2021-02-23T14:44:07+01:00 +draft: false +layout: "category" +--- + +This page will fill itself. diff --git a/content/know/category/physics.md b/content/know/category/physics.md new file mode 100644 index 0000000..7b0eaed --- /dev/null +++ b/content/know/category/physics.md @@ -0,0 +1,9 @@ +--- +title: "Physics" +firstLetter: "P" +date: 2021-02-23T14:44:11+01:00 +draft: false +layout: "category" +--- + +This page will fill itself. diff --git a/content/know/category/quantum-mechanics.md b/content/know/category/quantum-mechanics.md new file mode 100644 index 0000000..bc36a6f --- /dev/null +++ b/content/know/category/quantum-mechanics.md @@ -0,0 +1,9 @@ +--- +title: "Quantum mechanics" +firstLetter: "Q" +date: 2021-02-23T14:38:56+01:00 +draft: false +layout: "category" +--- + +This page will fill itself. diff --git a/content/know/concept/_index.md b/content/know/concept/_index.md new file mode 100644 index 0000000..956724a --- /dev/null +++ b/content/know/concept/_index.md @@ -0,0 +1,8 @@ +--- +title: "List of concepts" +date: 2021-02-22T20:38:58+01:00 +draft: false +layout: "know-list" +--- + +This is an alphabetical list of the concepts in this knowledge base. diff --git a/content/know/concept/blochs-theorem/index.pdc b/content/know/concept/blochs-theorem/index.pdc new file mode 100644 index 0000000..1828d8a --- /dev/null +++ b/content/know/concept/blochs-theorem/index.pdc @@ -0,0 +1,115 @@ +--- +title: "Bloch's theorem" +firstLetter: "B" +publishDate: 2021-02-22 +categories: +- Quantum mechanics + +date: 2021-02-22T20:02:14+01:00 +draft: false +markup: pandoc +--- + +# Bloch's theorem +In quantum mechanics, **Bloch's theorem** states that, +given a potential $V(\vec{r})$ which is periodic on a lattice, +i.e. $V(\vec{r}) = V(\vec{r} + \vec{a})$ +for a primitive lattice vector $\vec{a}$, +then it follows that the solutions $\psi(\vec{r})$ +to the time-independent Schrödinger equation +take the following form, +where the function $u(\vec{r})$ is periodic on the same lattice, +i.e. $u(\vec{r}) = u(\vec{r} + \vec{a})$: + +$$ +\begin{aligned} + \boxed{ + \psi(\vec{r}) = u(\vec{r}) e^{i \vec{k} \cdot \vec{r}} + } +\end{aligned} +$$ + +In other words, in a periodic potential, +the solutions are simply plane waves with a periodic modulation, +known as **Bloch functions** or **Bloch states**. + +This is suprisingly easy to prove: +if the Hamiltonian $\hat{H}$ is lattice-periodic, +then both $\psi(\vec{r})$ and $\psi(\vec{r} + \vec{a})$ +are eigenstates with the same energy: + +$$ +\begin{aligned} + \hat{H} \psi(\vec{r}) = E \psi(\vec{r}) + \qquad + \hat{H} \psi(\vec{r} + \vec{a}) = E \psi(\vec{r} + \vec{a}) +\end{aligned} +$$ + +Now define the unitary translation operator $\hat{T}(\vec{a})$ such that +$\psi(\vec{r} + \vec{a}) = \hat{T}(\vec{a}) \psi(\vec{r})$. +From the previous equation, we then know that: + +$$ +\begin{aligned} + \hat{H} \hat{T}(\vec{a}) \psi(\vec{r}) + = E \hat{T}(\vec{a}) \psi(\vec{r}) + = \hat{T}(\vec{a}) \big(E \psi(\vec{r})\big) + = \hat{T}(\vec{a}) \hat{H} \psi(\vec{r}) +\end{aligned} +$$ + +In other words, if $\hat{H}$ is lattice-periodic, +then it will commute with $\hat{T}(\vec{a})$, +i.e. $[\hat{H}, \hat{T}(\vec{a})] = 0$. +Consequently, $\hat{H}$ and $\hat{T}(\vec{a})$ must share eigenstates $\psi(\vec{r})$: + +$$ +\begin{aligned} + \hat{H} \:\psi(\vec{r}) = E \:\psi(\vec{r}) + \qquad + \hat{T}(\vec{a}) \:\psi(\vec{r}) = \tau \:\psi(\vec{r}) +\end{aligned} +$$ + +Since $\hat{T}$ is unitary, +its eigenvalues $\tau$ must have the form $e^{i \theta}$, with $\theta$ real. +Therefore a translation by $\vec{a}$ causes a phase shift, +for some vector $\vec{k}$: + +$$ +\begin{aligned} + \psi(\vec{r} + \vec{a}) + = \hat{T}(\vec{a}) \:\psi(\vec{r}) + = e^{i \theta} \:\psi(\vec{r}) + = e^{i \vec{k} \cdot \vec{a}} \:\psi(\vec{r}) +\end{aligned} +$$ + +Let us now define the following function, +keeping our arbitrary choice of $\vec{k}$: + +$$ +\begin{aligned} + u(\vec{r}) + = e^{- i \vec{k} \cdot \vec{r}} \:\psi(\vec{r}) +\end{aligned} +$$ + +As it turns out, this function is guaranteed to be lattice-periodic for any $\vec{k}$: + +$$ +\begin{aligned} + u(\vec{r} + \vec{a}) + &= e^{- i \vec{k} \cdot (\vec{r} + \vec{a})} \:\psi(\vec{r} + \vec{a}) + \\ + &= e^{- i \vec{k} \cdot \vec{r}} e^{- i \vec{k} \cdot \vec{a}} e^{i \vec{k} \cdot \vec{a}} \:\psi(\vec{r}) + \\ + &= e^{- i \vec{k} \cdot \vec{r}} \:\psi(\vec{r}) + \\ + &= u(\vec{r}) +\end{aligned} +$$ + +Then Bloch's theorem follows from +isolating the definition of $u(\vec{r})$ for $\psi(\vec{r})$. diff --git a/content/know/concept/convolution-theorem/index.pdc b/content/know/concept/convolution-theorem/index.pdc new file mode 100644 index 0000000..fc96f30 --- /dev/null +++ b/content/know/concept/convolution-theorem/index.pdc @@ -0,0 +1,100 @@ +--- +title: "Convolution theorem" +firstLetter: "C" +publishDate: 2021-02-22 +categories: +- Mathematics + +date: 2021-02-22T21:35:23+01:00 +draft: false +markup: pandoc +--- + +# Convolution theorem + +The **convolution theorem** states that a convolution in the direct domain +is equal to a product in the frequency domain. This is especially useful +for computation, replacing an $\mathcal{O}(n^2)$ convolution with an +$\mathcal{O}(n \log(n))$ transform and product. + +## Fourier transform + +The convolution theorem is usually expressed as follows, where +$\hat{\mathcal{F}}$ is the [Fourier transform](/know/concept/fourier-transform/), +and $A$ and $B$ are constants from its definition: + +$$\begin{aligned} + \boxed{ + \begin{aligned} + A \cdot (f * g)(x) &= \hat{\mathcal{F}}^{-1}\{\tilde{f}(k) \: \tilde{g}(k)\} \\ + B \cdot (\tilde{f} * \tilde{g})(k) &= \hat{\mathcal{F}}\{f(x) \: g(x)\} + \end{aligned} + } +\end{aligned}$$ + +To prove this, we expand the right-hand side of the theorem and +rearrange the integrals: + +$$\begin{aligned} + \hat{\mathcal{F}}^{-1}\{\tilde{f}(k) \: \tilde{g}(k)\} + &= B \int_{-\infty}^\infty \tilde{f}(k) \Big( A \int_{-\infty}^\infty g(x') \exp(i s k x') \dd{x'} \Big) \exp(-i s k x) \dd{k} + \\ + &= A \int_{-\infty}^\infty g(x') \Big( B \int_{-\infty}^\infty \tilde{f}(k) \exp(- i s k (x - x')) \dd{k} \Big) \dd{x'} + \\ + &= A \int_{-\infty}^\infty g(x') f(x - x') \dd{x'} + = A \cdot (f * g)(x) +\end{aligned}$$ + +Then we do the same thing again, this time starting from a product in +the $x$-domain: + +$$\begin{aligned} + \hat{\mathcal{F}}\{f(x) \: g(x)\} + &= A \int_{-\infty}^\infty f(x) \Big( B \int_{-\infty}^\infty \tilde{g}(k') \exp(- i s x k') \dd{k'} \Big) \exp(i s k x) \dd{x} + \\ + &= B \int_{-\infty}^\infty \tilde{g}(k') \Big( A \int_{-\infty}^\infty f(x) \exp(i s x (k - k')) \dd{x} \Big) \dd{k'} + \\ + &= B \int_{-\infty}^\infty \tilde{g}(k') \tilde{f}(k - k') \dd{k'} + = B \cdot (\tilde{f} * \tilde{g})(k) +\end{aligned}$$ + + +## Laplace transform + +For functions $f(t)$ and $g(t)$ which are only defined for $t \ge 0$, +the convolution theorem can also be stated using the Laplace transform: + +$$\begin{aligned} + \boxed{(f * g)(t) = \hat{\mathcal{L}}^{-1}\{\tilde{f}(s) \: \tilde{g}(s)\}} +\end{aligned}$$ + +Because the inverse Laplace transform $\hat{\mathcal{L}}^{-1}$ is quite +unpleasant, the theorem is often stated using the forward transform +instead: + +$$\begin{aligned} + \boxed{\hat{\mathcal{L}}\{(f * g)(t)\} = \tilde{f}(s) \: \tilde{g}(s)} +\end{aligned}$$ + +We prove this by expanding the left-hand side. Note that the lower +integration limit is 0 instead of $-\infty$, because we set both $f(t)$ +and $g(t)$ to zero for $t < 0$: + +$$\begin{aligned} + \hat{\mathcal{L}}\{(f * g)(t)\} + &= \int_0^\infty \Big( \int_0^\infty g(t') f(t - t') \dd{t'} \Big) \exp(- s t) \dd{t} + \\ + &= \int_0^\infty \Big( \int_0^\infty f(t - t') \exp(- s t) \dd{t} \Big) g(t') \dd{t'} +\end{aligned}$$ + +Then we define a new integration variable $\tau = t - t'$, yielding: + +$$\begin{aligned} + \hat{\mathcal{L}}\{(f * g)(t)\} + &= \int_0^\infty \Big( \int_0^\infty f(\tau) \exp(- s (\tau + t')) \dd{\tau} \Big) g(t') \dd{t'} + \\ + &= \int_0^\infty \Big( \int_0^\infty f(\tau) \exp(- s \tau) \dd{\tau} \Big) g(t') \exp(- s t') \dd{t'} + \\ + &= \int_0^\infty \tilde{f}(s) g(t') \exp(- s t') \dd{t'} + = \tilde{f}(s) \: \tilde{g}(s) +\end{aligned}$$ diff --git a/content/know/concept/dirac-delta-function/index.pdc b/content/know/concept/dirac-delta-function/index.pdc new file mode 100644 index 0000000..3982afc --- /dev/null +++ b/content/know/concept/dirac-delta-function/index.pdc @@ -0,0 +1,109 @@ +--- +title: "Dirac delta function" +firstLetter: "D" +publishDate: 2021-02-22 +categories: +- Mathematics +- Physics + +date: 2021-02-22T21:35:38+01:00 +draft: false +markup: pandoc +--- + +# Dirac delta function + +The **Dirac delta function** $\delta(x)$, often just called the **delta function**, +is an infinitely narrow discontinuous "spike" at $x = 0$ whose area is +defined to be 1: + +$$\begin{aligned} + \boxed{ + \delta(x) = + \begin{cases} + +\infty & \mathrm{if}\: x = 0 \\ + 0 & \mathrm{if}\: x \neq 0 + \end{cases} + \quad \mathrm{and} \quad + \int_{-\varepsilon}^\varepsilon \delta(x) \dd{x} = 1 + } +\end{aligned}$$ + +It is sometimes also called the **sampling function**, due to its most +important property: the so-called **sampling property**: + +$$\begin{aligned} + \boxed{ + \int f(x) \: \delta(x - x_0) \: dx = \int f(x) \: \delta(x_0 - x) \: dx = f(x_0) + } +\end{aligned}$$ + +$\delta(x)$ is thus an effective weapon against integrals. This may not seem very +useful due to its "unnatural" definition, but in fact it appears as the +limit of several reasonable functions: + +$$\begin{aligned} + \delta(x) + = \lim_{n \to +\infty} \!\Big\{ \frac{n}{\sqrt{\pi}} \exp(- n^2 x^2) \Big\} + = \lim_{n \to +\infty} \!\Big\{ \frac{n}{\pi} \frac{1}{1 + n^2 x^2} \Big\} + = \lim_{n \to +\infty} \!\Big\{ \frac{\sin(n x)}{\pi x} \Big\} +\end{aligned}$$ + +The last one is especially important, since it is equivalent to the +following integral, which appears very often in the context of +[Fourier transforms](/know/concept/fourier-transform/): + +$$\begin{aligned} + \boxed{ + \delta(x) + %= \lim_{n \to +\infty}