{"id":850,"date":"2014-02-04T23:27:40","date_gmt":"2014-02-05T04:27:40","guid":{"rendered":"http:\/\/littlesvr.ca\/grumble\/?p=850"},"modified":"2018-09-03T10:39:27","modified_gmt":"2018-09-03T15:39:27","slug":"setting-up-sendmail-on-a-dynamic-ip-part3-dkim","status":"publish","type":"post","link":"http:\/\/littlesvr.ca\/grumble\/2014\/02\/04\/setting-up-sendmail-on-a-dynamic-ip-part3-dkim\/","title":{"rendered":"Setting up Sendmail on a dynamic IP, part3: DKIM"},"content":{"rendered":"<p>Compared to <a href=\"http:\/\/littlesvr.ca\/grumble\/2014\/01\/26\/setting-up-sendmail-on-a-dynamic-ip-part1-go-through-isps-smtp\/\">part1<\/a> and <a href=\"http:\/\/littlesvr.ca\/grumble\/2014\/01\/26\/setting-up-sendmail-on-a-dynamic-ip-part2-spf\/\">part2<\/a>, DKIM took a lot of effort to understand. The concept is relatively simple but the documentation is shit. It doesn&#8217;t help that there are at least three implementations of DKIM, though eventually (after some days) I figured out OpenDKIM is the only one that still matters.<\/p>\n<p>In typical open source way the guides on the website are.. the ASCII readme files that come with the distribution.. which I don&#8217;t have a problem with in principle but in practice never works well. Plain text is hard to read in a browser. Anyway, that wasn&#8217;t the real problem. The real problem is that the documentation is in bizarre order, is definitely not for newbies, and has very significant parts missing. So as I usually do &#8211; I wrote my own notes and I&#8217;ll publish them here.<\/p>\n<h3>Step1: Install OpenDKIM<\/h3>\n<p>OpenDKIM doesn&#8217;t come with Slackware, and strangely doesn&#8217;t even have a slackbuild on <a href=\"http:\/\/slackbuilds.org\/\">slackbuilds.org<\/a>. So I had to get the source and compile it myself. Not much of a problem since I&#8217;m a slackware user, but yes a problem because I&#8217;m a linux user.<\/p>\n<p>Turns out the currently latest version of OpenDKIM (2.9.0) doesn&#8217;t compile on linux of any kind, because the code is using some BSD-only functions and the configure script didn&#8217;t know to replace them with non-BSD versions. I found a bug report and a guy in there claimed (in a backwards kind of way) that the bug will be fixed in the next version, but I didn&#8217;t have the time to wait for that so I got the previous version, 2.8.4, which worked.<\/p>\n<p>I normally don&#8217;t mind when new software installs into \/usr\/local, but I hate when it starts to use ridiculous directories like \/usr\/local\/var. After trying to accept that for a day I went back and started over &#8211; making sure it&#8217;s installed into \/usr instead, here are the commands I used:<\/p>\n<p><code>.\/configure --prefix=\/usr<br \/>\nmake<br \/>\nmake install<br \/>\nldconfig<\/code><\/p>\n<p>The the rest of the time was spent figuring out why the instructions in the <a href=\"http:\/\/opendkim.org\/opendkim-README\">official readme<\/a> are so retarded.<\/p>\n<h3>Step2: Generate keys<\/h3>\n<p>For reference: in the rest of this guide I will use my setup as an example. In this setup my SELECTOR is littlesvr-dkim (it can be any random string, though might as well call it your domain name).<\/p>\n<p>First thing you need to do is generate a public\/private key pair. This is actually quite easy because opendkim comes with a tool that will do it. The command sequence I used was:<\/p>\n<p><code>mkdir \/etc\/dkim<br \/>\ncd \/etc\/dkim<br \/>\nchmod 700 .<br \/>\nopendkim-genkey -s littlesvr-dkim<br \/>\nls -al<\/code><\/p>\n<p>Make sure that the dkim directory and the files in it (particularly the keys) are only readable by root. If you&#8217;re wondering as I did &#8211; <code>opendkim-genkey<\/code> will generate a 1024bit key by default, which should be good enough for a number of years to come.<\/p>\n<p>The command will generate two files, in my case named littlesvr.ca.private and littlesvr-dkim.txt (the latter is the public key in a DNS record format).<\/p>\n<h3>Step3: Configure opendkim<\/h3>\n<p>This almost doesn&#8217;t deserve its own step. First copy the sample config from \/usr\/share\/doc\/opendkim\/opendkim.conf.simple to \/etc\/dkim\/opendkim.conf and then the only change you have to make inside is the KeyFile path &#8211; it was \/etc\/dkim\/littlesvr.ca.private for me.<\/p>\n<h3>Step4: Create a startup script<\/h3>\n<p>Usually a startup script is something you make when you&#8217;re done, but in this case you really want it to begin with, because the command to launch opendkim is complicated, so take your time now to create the script \/etc\/rc.d\/rc.dkim, use this below as a starting point (replace any references to my server littlesvr.ca with your own server, private key path, and selector:<\/p>\n<pre>#!\/bin\/sh\r\n# Start\/stop\/restart the domain keys identified mail milter daemon.\r\n\r\n# Comma-separated (no spaces) list of the domains you want\r\n# opendkim to work with:\r\nMYDOMAINS=littlesvr.ca\r\n# The name with full path of the private key you generated with opendkim-genkey\r\nPRIVATE_KEY=\/etc\/dkim\/littlesvr-dkim.private\r\n# Your SELECTOR:\r\nSELECTOR=littlesvr-dkim\r\n\r\ndkim_start() {\r\n   if [ -x \/usr\/sbin\/opendkim ]; then\r\n     echo \"Starting domain keys identified mail milter daemon \/usr\/sbin\/opendkim\"\r\n     \/usr\/bin\/logger \"Starting domain keys identified mail milter daemon \/usr\/sbin\/opendkim\"\r\n     \/usr\/sbin\/opendkim   -l -p local:\/var\/dkim\/dkim.sock \r\n     -d $MYDOMAINS -k $PRIVATE_KEY -s $SELECTOR\r\n   fi\r\n}\r\n\r\n# Stop dkim:\r\ndkim_stop() {\r\n   \/usr\/bin\/logger \"Stopping domain keys identified mail milter daemon\"\r\n   killall opendkim\r\n   if [ -S \/var\/dkim\/dkim.sock ]; then\r\n     rm \/var\/dkim\/dkim.sock\r\n   fi\r\n}\r\n\r\n# Restart dkim:\r\ndkim_restart() {\r\n   dkim_stop\r\n   sleep 1\r\n   dkim_start\r\n}\r\n\r\ncase \"$1\" in\r\n'start')\r\n   dkim_start\r\n   ;;\r\n'stop')\r\n   dkim_stop\r\n   ;;\r\n'restart')\r\n   dkim_restart\r\n   ;;\r\n*)\r\n   echo \"usage $0 start|stop|restart\"\r\nesac<\/pre>\n<p>You want to make sure that the script has execute permissions and you run it automatically from rc.local. I expect in most setups it doesn&#8217;t matter when it starts relative to Sendmail.<\/p>\n<h3>Step5: Set up DNS records<\/h3>\n<p>If everything worked so far &#8211; you can go ahead and publish the appropriate DNS records. It&#8217;s safe to do this now because those records won&#8217;t be used until your sendmail is reconfigured (next step).<\/p>\n<p>This is probably what the official setup guide is the worst at. Basically it tells you to go and read the RFC &#8211; yeah, thanks.<br \/>\nFirst you have to create a TXT record for _domainkey.whateveryourserver.ca &#8211; which in my case is _domainkey.littlesvr.ca. The value of the record should be &#8220;o=-&#8221; which means all the outgoing mail will be signed (as opposed to some of it).<\/p>\n<p>The second record you have to create will have your actual key. This is another TXT record, this time for SELECTOR._domainkey.whateveryourserver.ca (in my case for littlesvr-dkim._domainkey.littlesvr.ca) with the value from the .txt file generated by oepndkim-genkey. It looked to me like I had to remove some whitespace and cut out everything from that file between the () brackets, but maybe I didn&#8217;t have to. What I ended up using as a value is this (wrapped for the blog):<\/p>\n<p><code>v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC36RsUh9bccxZAy<br \/>\n2NuOr4nfD3+nxXJQVsGCt3iF\/pEwZZjkkqzfiGUkfTDMICviDgfcqES<br \/>\naQg8GPwFd\/IKTSErQy09g2XPtvbro3CtAHnarkjTji4RUqiptcdk3H<br \/>\nK83rKdx5hXH0mVITojobn+dsT1+pqToBt4TTQ0CfY2SyiDVQIDAQAB<\/code><\/p>\n<p>These records obviously need to be created in your DNS server. If you have your own &#8211; you know what to do. In my case &#8211; I went to my dynamic DNS provider&#8217;s website and created them there. They are static, and don&#8217;t need to be updated as my server&#8217;s IP changes.<\/p>\n<p>You can test your changes with dig. I ran these two:<\/p>\n<p><code>dig _domainkey.littlesvr.ca TXT<br \/>\ndig littlesvr-dkim._domainkey.littlesvr.ca TXT<\/code><\/p>\n<p>I couldn&#8217;t figure out whether opendkim-testkey didn&#8217;t work or it was silently telling me that my setup was correct.<\/p>\n<h3>Step6: Update sendmail configuration<\/h3>\n<p>Very little needs to be done here, most of the work is the typical pain of updating sendmail config files. But if you&#8217;ve set up your own sendmail, you&#8217;re probably able to remember which .mc file had your (pre-compiled) configuration. Mine was \/usr\/share\/sendmail\/cf\/cf\/sendmail-slackware-tls-sasl-andrew.mc<\/p>\n<p>I edited it and added these lines right after LOCAL_DOMAIN (but probably doesn&#8217;t matter where):<\/p>\n<p><code>dnl# DKIM Support (added 4 feb 2014)<br \/>\nINPUT_MAIL_FILTER(`dkim',`S=local:\/var\/dkim\/dkim.sock')dnl<\/code><\/p>\n<p>Yours will be the same assuming you configured opendkim with the same prefix as I recommended.<\/p>\n<p>To update the actual configuration I ran .\/Build sendmail-slackware-tls-sasl-andrew.mc (in that dir) and copied the built sendmail-slackware-tls-sasl-andrew.cf overwriting \/etc\/mail\/sendmail.cf<\/p>\n<p>Before restarting sendmail &#8211; double check your DNS settings, and that opendkim is running.<\/p>\n<h3>Step7: Test<\/h3>\n<p>Once your DNS records are set and your Sendmail is passing emails through OpenDKIM &#8211; you&#8217;re ready to test it, and you should test it as soon as you can, because if something didn&#8217;t work right &#8211; you may end up with sent mails that won&#8217;t arrive at their destination and you won&#8217;t get a bounce message to know it happened.<\/p>\n<p>Luckily testing is quick and easy &#8211; just send an email to check-auth@verifier.port25.com (the same service I used in <a href=\"http:\/\/littlesvr.ca\/grumble\/2014\/01\/26\/setting-up-sendmail-on-a-dynamic-ip-part2-spf\/\">part2<\/a>).<\/p>\n<p>If you&#8217;ve done the same stuff I have in these three blog posts &#8211; you should be in awesome shape spam-wise! I should have done this years ago, if only I had a guide like this I would have :)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Compared to part1 and part2, DKIM took a lot of effort to understand. The concept is relatively simple but the documentation is shit. It doesn&#8217;t help that there are at least three implementations of DKIM, though eventually (after some days) I figured out OpenDKIM is the only one that still matters. In typical open source &hellip; <\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":{"0":"entry","1":"post","2":"publish","3":"author-andrew","4":"post-850","6":"format-standard","7":"category-opensource"},"_links":{"self":[{"href":"http:\/\/littlesvr.ca\/grumble\/wp-json\/wp\/v2\/posts\/850","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/littlesvr.ca\/grumble\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/littlesvr.ca\/grumble\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/littlesvr.ca\/grumble\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"http:\/\/littlesvr.ca\/grumble\/wp-json\/wp\/v2\/comments?post=850"}],"version-history":[{"count":13,"href":"http:\/\/littlesvr.ca\/grumble\/wp-json\/wp\/v2\/posts\/850\/revisions"}],"predecessor-version":[{"id":1283,"href":"http:\/\/littlesvr.ca\/grumble\/wp-json\/wp\/v2\/posts\/850\/revisions\/1283"}],"wp:attachment":[{"href":"http:\/\/littlesvr.ca\/grumble\/wp-json\/wp\/v2\/media?parent=850"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/littlesvr.ca\/grumble\/wp-json\/wp\/v2\/categories?post=850"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/littlesvr.ca\/grumble\/wp-json\/wp\/v2\/tags?post=850"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}