Postfix and Servers with invalid Helo

I like to keep higher than “normal” security on our email servers. One such setting in Postfix is:

smtpd_helo_required = yes

Along with this setting enabled, you need to specify who is allowed and who should be blocked via:

smtpd_helo_restrictions = [bunch of settings here...]

In this article, I will be discussing:

smtpd_helo_restrictions = permit_mynetworks, check_helo_access regexp:/etc/postfix/helo_access, [other options not discussed]

I think that blocking mail servers that don’t properly have DNS set up is a GOOD thing. There are plenty of servers that don’t meet RFC specifications, many of which are spammers who don’t want their server discoverable via DNS routes. This makes it so that spam originating from them does not return to their server as a bounced email and flood the spammer’s own system. So enabling the smtpd_helo_restrictions blocks a TON of spam.

Inevitably a customer utilizes a service with a badly configured email server and their messages need to get through this blocking mechanism. That’s where the helo_access file is useful. With the configuration above, postfix uses regular expression matching to validate DNS names and IP addresses and allow them to get around the helo_restriction and DNS validation. Set up the file like this.

Say I’m encountering a source server or multiple source servers on IP addresses 50.0.0.1 and 50.0.0.2. Those servers are announcing themselves as mxbox50.bitwiz.net but they have not added an entry in DNS for mxbox50 to resolve to either of those IP addresses. On my receiving server, I open the /etc/postfix/helo_access file with my favorite Linux text editor and add the following lines:

/^50\.0\.0\.1$/ OK
/^50\.0\.0\.2$/ OK
/^mxbox50\.bitwiz\.net$/ OK

Save the file.

Execute the following commands:

[me@mxbox50 me]# postmap /etc/postfix/helo_access
[me@mxbox50 me]# postfix reload

Postfix will now allow the invalid helo response to pass and be delivered. All other badly configured email servers with invalid helo remain blocked.

In regular expressions, /^ starts the thing you’re looking for (a search), a \ will escape the period . character which typically means something else in a regular expression, and $/ finishes or closes the regular expression. This is an example of an exact match regular expression. No other variations will match and pass.

Providing Email client autoconfiguration information

This is a re-post of the information from the moens.ch blog (which no longer exists) pulled from archive.org. Part of a discussion on Stack Overflow. I have not personally validated any of this yet. Use at your own risk.

If you’ve ever configured a Gmail or Hotmail account in a mail client such as Thunderbird, Outlook or Apple Mail you will have noticed that all it asks of you is your username and password and automatically sets up the mail server hostnames, port numbers and connection settings. However, if you set up an email account hosted on your own mail server run on non-proprietary your mail client – at best – tries to make an educated guess as to what your SMTP and IMAP servers are. If you follow certain standards (e.g. calling your SMTP server smtp.maildomain.com) this might work out, however, if you do not (and got reasons to do so), you find yourself constantly having to manually enter information.

Auto configuration is most handy though if third parties are using your mail server too. It saves you the hassle of bringing up FAQ pages on your website explaining your users how to set up their account. With auto configuration they just enter their username and password – and everything will (should) work.

I found documentation on this for all things except Thunderbird is scarce on the internet and you only find individual bits and pieces. I took an afternoon to set up my mail server to support auto configuration for most well known mail clients.

Before you can start

Before you begin you have to gather the following pieces of information:

  • Incoming mail server
    • Hostname
    • Protocol (IMAP or POP3)
    • Whether SSL is available or not
    • Port number (IMAP: 143, IMAPs: 993, POP3: 110, POP3s: 995)
    • Username format (full email address or just the local part)
    • Password mechanism (plain or encrypted)
  • Outgoing mail server
    • Hostname
    • Port number (most likely 587. If your SMTP server still only listens on port 25 many people will have troubles connecting as ISPs around the world started blocking this port. Enable the submission port 587, which on postfix for example is up by default)
    • Whether SSL or STARTTLS should be used
    • Username format
    • Password mechanism

In essence

All mail clients – in essence – perform auto configuration or auto discovery in a similar way. Mostly they request an XML file from a specific location which contains the information they need. It is up to you to put that XML file at exactly the location they expect and follow the format they expect it to be in. The only client which doesn’t seem to do that is Mail on iOS (iPhone, iPod and iPad). No worry though, I found a solution for that too.

Mozilla Thunderbird

The process for email server admins to provide auto configuration for Thunderbird is actually very well documented here. I summarize:

Thunderbird assumes that everything after the @-sign of the username you entered is your email domain. If the user enters fred@example.com, the email domain will be example.com. It then looks for a configuration file at http://autoconfig.example.com/mail/config-v1.1.xml to find the settings for this domain. You can find the authoritative description of this XML file here.

The format allows you to specify more than on server of each type (incoming and outcoming). For example my IMAP server is available on port 143 using STARTTLS and on 993 using IMAPs. The live example for my domain mylansite.org can be found here: http://autoconfig.mylansite.org/mail/config-v1.1.xml.

In my case, the username is the full email address. Hence you will find this in my configuration file:

<username>%EMAILADDRESS%</username>

If on your server only the local part of the email address (the string before the @-sign) is used for authentication, use the token %EMAILLOCALPART%.

Now all you have to do is set up your config file, create a vhost on your webserver for autoconfig.yourdomain.com, place the config-v1.1.xml file in the /mail subfolder and bob’s your uncle. If you are hosting multiple email domains, the Thunderbird Autoconfiguration documentation contains a brilliant example for how to set up an Apache rewrite rule to automatically match on all host names called autoconfig.*.

Microsoft Outlook

This is where things started to get tricky as documentation was scarce. Outlook works brilliantly when connecting to an Exchange server, tt figures out everything it needs to know, but how to make use of this mechanism you wonder? Well, wonder no longer. It isn’t as simple as the Thunderbird implementation, but the concept is very similar.

Outlook performs an HTTP POST request to https://autodiscover.emaildomain.com/autodiscover/autodiscover.xml with the following content:

<?xml version="1.0" encoding="utf-8"?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
  <Request>
    <AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
    <EMailAddress>fred@emaildomain.com</EMailAddress>
  </Request>
</Autodiscover>

There is some decent documentation in this MS TechNet article on how to format the response. To very quickly cut to the chase, you can find my example here with the minimum required to set up a simple email account. You will notice that the <LoginName> is blank. I’ll get to that in a minute: https://ns2.samhostuk.net/autodiscover/autodiscover.xml

Remember that this POST request will go via HTTPs and not HTTP. You don’t want to have different SSL certificates for each email domain you are hosting, each matching autodiscover.emaildomain.com (also considering that Apache cannot have name based virtual hosts with different SSL certs). There is a very elegant way to solve this:

Outlook first does a DNS lookup for a SRV record at _autodiscover._tcp.emaildomain.com to find the address of the autodiscover server. This record should have the following format:

0 0 443 ssl.mailprovider.com

This means that instead of looking for the XML file at https://autodiscover.emaildomain.com/autodiscover/autodiscover.xml, Outlook will now look at https://ssl.mailprovider.com/autodiscover/autodiscover.xml. If you are running bind, the entry in your zone file will look somewhat like this:

_autodiscover._tcp      SRV       0 0 443 ns2.samhostuk.net.

If you want to test your record before going through the pain of firing up your Outlook client, run something like:

#> dig +short -t SRV _autodiscover._tcp.mydomain.com

This also means you do not have to set up an autodiscover subdomain for each email domain you host. You still however have to add this SRV record to each email domain’s DNS zone.

Getting the user’s email address in the response XML

I have found no documentation on valid tokens you can use in the response XML such as the %EMAILADDRESS% token honored by Thunderbird. This means it’s up to you to populate the <LoginName> element on the server side. Fortunately, the client just posted it to you, so all you have to do is extract it from the POST data and print it into the output XML. PHP is my language of choice, but you can implement a similar solution in your preferred server side scripting language.

First, you need to tell Apache that .xml files should be sent through the PHP interpreter. Locate the <VirtualHost> directive for your SSL host (on my Ubuntu install it’s in /etc/apache/sites-available/default-ssl) and add the following line:

AddType application/x-httpd-php .php .php3 .php4 .php5 .xml

Save your config and reload Apache.

Then, edit your autodiscover.xml file and add some magic. Here is what mine looks like (I am a believer that for this simple search, a preg_match is quicker than a full XML parse):

<?php
$raw = file_get_contents('php://input');
$matches = array();
preg_match('/<EMailAddress>(.*)<\/EMailAddress>/', $raw, $matches);
header('Content-Type: application/xml');
?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
  <Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
    <User>
      <DisplayName>myLANsite</DisplayName>
    </User>
    <Account>
      <AccountType>email</AccountType>
      <Action>settings</Action>
      <Protocol>
        <Type>IMAP</Type>
        <Server>ns2.samhostuk.net</Server>
        <Port>993</Port>
        <DomainRequired>off</DomainRequired>
        <SPA>off</SPA>
        <SSL>on</SSL>
        <AuthRequired>on</AuthRequired>
        <LoginName><?php echo $matches[1]; ?></LoginName>
      </Protocol>
      <Protocol>
        <Type>SMTP</Type>
        <Server>ns2.samhostuk.net</Server>
        <Port>465</Port>
        <DomainRequired>off</DomainRequired>
        <SPA>off</SPA>
        <SSL>on</SSL>
        <AuthRequired>on</AuthRequired>
        <LoginName><?php echo $matches[1]; ?></LoginName>
      </Protocol>
    </Account>
  </Response>
</Autodiscover>

To test your script, save a copy of the Autodiscover XML Request above into a local file called req.xml and then execute the below command to execute the request and validate the response:

cat req.xml | lwp-request -m POST https://autodiscover.mymaildomain.com/autodiscover/autodiscover.xml

If your _autodiscover._tcp SRV record and the autodiscover.xml file are correctly in place, Outlook users will be able to set up their email accounts absolutely hassle free.

Apple Mail on iOS (iPhone, iPod, iPad)

The Mail App on iOS works differently to Outlook at Thunderbird. It does not perform any lookups to discover settings. It’s got the built-in presets for providers such as Hotmail and Gmail, but makes not attempt to look up settings for any other mail domains. However, there is a way – through profiles. If you’ve got a Mac you’re in luck. If you have not, ask a friend with a Mac to lend it to you for five minutes ;-)

First, get your hands on the free iPhone Configuration Utility from Apple. Install it and run. Select Configuration Profiles on the left, click New and give it a name.

Select Email from the list of categories and click Configure. Here an example for the same config we’ve been using all throughout this article for my email domain. The important thing to notice is that I enter MAILADDR as value for the email address and user name. This is because I use a similar replace mechanism as I did on the Outlook autodiscover.xml file above. If you wish a simpler solution, you can just leave it blank and the user will be prompted for their email address.

Hit the Export button, select None as security (unless you’ve got a fancy signed cert for signing) and finish the export process. You will end up with a file called something.mobileconfig. Upload it to your web server at any desired location. Now  all you have to do is direct users to the location of your .mobileconfig file and the iP(hone|od|ad) will do its magic!

If you want some real magic, and if you used the MAILADDR “token” when creating the Configuration Profile, take a look at the iphone.php script below. It captures the email parameter either from GET or POST, opens up a local .mobileconfig file, replaces the MAILADDR token and outputs the file. The header() lines are vital – the download filename must have the extension .mobileconfig or the iDevice will not automatically detect it as a profile.

<?php if (isset($_REQUEST['email'])): ?>
  <?php
  header('Content-Type: text/plain');
  header("Content-Disposition: attachment; filename=\"mylansite.mobileconfig\"");
  $conf = file_get_contents('iphone.mobileconfig');
  $conf = str_replace('MAILADDR', $_REQUEST['email'], $conf);
  print $conf;
  ?>
<?php else: ?>
  <html>
  <head>
    <title>iPhone Email Auto Configuration</title>
    <meta name="viewport" content="width=device-width; initial-scale=1; user-scalable=no" />
  </head>
  <body style="font: 100% Verdana;">
    <form method="post" action="iphone.php">
      <p style="text-align: center">
        Enter your email address to obtain an automatic
        configuration profile for your %ISPNAME% Email Account.<br/>
        <br/><br/>
        <input type="text" name="email" style="height: 30px; width: 250px;"/><br/>
        <br/>
        <input type="submit" value="Submit" style="width: 100px; height: 30px;"/>
      </p>
    </form>
  </body>
</html>
<?php endif ?>

I am using a control panel back end for my mail host which is automatically sending a welcome email to the user and also provides a web mail interface. I extended the code which sends the welcome email to include a link to http://myhost.com/iphone.php?email=youraddress@myhost.com. Actually, I shorten it with bit.ly first using David Walsh’s neat little PHP example on how to access the bit.ly API, as the user will most likely have to manually enter the URL into their phone. So the user enters bit.ly/LODdtw into their iPhone browser, the profile gets downloaded, and all they have to provide is a Display Name, email address and password and the rest is automatically configured.

Cars and Batteries and Terminals Oh My, is it really red first?

Proper connection order first, details below.

For JUMP STARTING with 2 vehicles:

  1. Red jumper to positive (red +) of dead battery.
  2. Red jumper to positive (red +) of charged battery.
  3. Black jumper to negative (black -) of charged battery.
  4. Black jumper to dead car’s frame (engine bolt) – NOT negative terminal of dead battery.
    Keeps final connection spark away from the dead battery.
  5. Charge for 3-5 minutes.
  6. Start the dead car.
  7. Disconnect in reverse. #4, #3, #2, #1.

For INSTALLING a car battery:

  1. Red cable to positive (red +) terminal (wrench to frame does nothing – no circuit to connect).
  2. Black cable to negative (black -) terminal (wrench to frame does nothing – negative to negative).

For REMOVING a car battery:

  1. NEGATIVE (black -) terminal first (wrench to frame does nothing – negative to negative).
  2. Positive (red +) terminal second (wrench to frame does nothing – no circuit to connect).

Explanation of safety.

For jump starting – this method avoids arcing between cars and/or terminals and watches out for sparks when completing the circuit’s final connection which could ignite fumes around a lead-acid dead battery that might be leaking. The last connection in the circuit usually causes a spark so we (who know about electronics and circuits) don’t want that final connection to cause an explosion. The chances of an explosion are low – especially if you are outside and there is enough wind to blow fumes away. We have to mention the possibility of explosion because the gasses produced by lead-acid batteries can ignite from a spark. In some newer cars, jump terminals are available under the hood and batteries are stored in the trunk or wheel wells to increase distance away from jumper cable sparks.

For car battery assembly/disassembly – these methods are used to avoid the potential differences across the terminals of batteries and your metal (conductive) wrench and the car frame. We want to avoid making a circuit in any circumstance where the wrench is connected to a terminal while tightening the bolts.

I wrote this post because the internet is riddled with frustratingly, infuriatingly, annoyingly incomplete answers which only confuse people. Some are so detailed that the answer is buried in the post. Others talk about one without the others and can mislead people easily. This post has the most common answers first at the top of the post, and all in a single place. With only a brief explanation as a reminder.

I needed this.

Thunderbird or Outlook Won’t Save Sent Messages (imap/dovecot)

You’re getting an error that Outlook or Thunderbird cannot save to the sent folder and you’re connected to an imap server running dovecot. You’re also seeing Maximum Number of User+IP connections in /var/log/maillog as people try to send email messages.

Please edit the following configuration to accept more simultaneous connections from a single IP. Add it if missing.

/etc/dovecot/dovecot.conf

Add or edit the line and increase it.

mail_max_userip_connections = 50

Restart dovecot via

systemctl restart dovecot

Roundcube Auth Fail with ISPConfig3 and Dovecot

After an upgrade of ISPconfig to the latest version, I told ISPConfig to “reconfigure” services. Roundcube started these entries in the /usr/share/roundcubemail/logs/imap.log:

[19-Dec-2021 23:26:53 +0000]: <21grgvah> [A61A] S: A0001 NO [UNAVAILABLE] Temporary authentication failure. [mail.domain.com:2021-12-19 23:26:53]

At first I thought this was a user password problem, but confirmed the user’s password was accurate. After quite a lot of debug, I found that it wasn’t a Roundcube login issue (I had properly upgraded that software), it was a dovecot issue. Roundcube authenticates against the dovecot imap server, the communication between roundcube and dovecot was working. It was dovecot that was broken when communicating to the SQL database (found in /var/log/maillog).

ISPConfig updates apparently are not writing dovecot-sql.conf files properly for dovecot. Some password characters that are acceptable by MySQL cause errors in dovecot’s attempts to read the sql configuration file. You need to encapsulate the login credentials in double quotes for the authentication to operate correctly. Unfortunately ISPConfig has been removing the quotes with every upgrade. UGH!

This is my blog entry to remember to correct this on mail servers configured like this.

Example fix in /etc/dovecot/dovecot-sql.conf

Original ISPConfig3 Dovecot Config:

driver = mysql
connect = host=localhost dbname=dbispconfig user=ispconfiguser password=RandomPasswordWithSpecialChars port=3306

Modified Code to make Dovecot happy and properly authenticate to the database (notice the quotes):

driver = mysql
connect = "host=localhost dbname=dbispconfig user=ispconfiguser password=RandomPasswordWithSpecialChars port=3306"

I don’t know which character is specifically breaking the connect line, I suspect it might be either # or * but I’m not sure which and haven’t tested it thoroughly. Hope this helps anyone else with this authentication problem.

Convert SSL crt to pem

Linux Text

openssl rsa -in ssl.key -out ssl.pem -outform PEM
openssl x509 -in ssl.crt -out ssl.pem -outform PEM

Windows Binary

openssl x509 -inform DER -outform PEM -in ssl.crt -out ssl.pem -text

Hidden Google Drive Menu

If you thought they removed the feature to add shared folders to your own drive, you can be relieved to know that it still exists!!!

In your browser, open up: drive.google.com

Navigate to the “Shared With Me” area (left column).

Select an item or folder (single click to highlight it).

Next use SHIFT-Z to activate a hidden menu that will allow you to add the item or folder to your own Google Drive.

THAT’S IT!

Enjoy.

Add/Swap UniFi Security Gateway (USG) to Existing Network with Another Router and Existing Controller

  • In Unifi Controller => Networks set an IP range DIFFERENT from your current one
  • On your “old” router/firewall hard code a DNS resolve for “unifi” to your Controller IP
    I added: unifi.domain.website.com (our windows domain and corresponding DNS is running on a sub-domain).
    You can verify this works on your domain by opening a CMD and type “ping unifi” … it should resolve now.
  • Connect the USG WAN port to your LAN – Controller should get a LAN IP via DHCP.
  • In the Controller adopt the USG
  • In the Controller configure WAN port to your real WAN data (static IP, whatever etc.).
    Note: The Controller will show the USG forever as “Provisioning”. Wait a few minutes, then…
  • Replace your old firewall/router with the USG (WAN to WAN Port, LAN to LAN port)…
  • In Unifi Controller => Networks set the LAN IP range back to the one you desire.

Resizing KVM qcow2 images

Expanding images

  1. Shut down the virtual machine
  2. Resize the image with
    qemu-img resize image.qcow2 +SIZE
    Where SIZE is the size (e.g. 10G for 10 gigabytes).
  3. Boot into gparted live and resize the partition.

Shrinking images

  1. Boot into gparted live and resize the partition smaller.
  2. If you managed to resize the partition from within the virtual machine (and thus didn’t shut it down already for resizing), shut it down now.
  3. KVM/QEMU images are stored in /var/lib/libvirt/images by default. I store them under /storage/images for my purposes. This process is done by root-only, so su is acceptable in this case. Create a new smaller qcow2 file to store the copied data
    qemu-img create -f qcow2 -o preallocation=metadata newimage.qcow2 NEW_SIZE
    where NEW_SIZE is the size (10G for the example at the start).
  4. Resize the image by copying the old image into the new one.virt-resize oldimage.qcow2 newimage.qcow2 If the image created in the previous step is larger than the combined partitions on the old image, virt-resize will inform you of a surplus and create a new partition. You can still terminate the process without data loss and go back to step #3 to create a smaller image. If the image is smaller than the partitions, virt-resize will fail and inform you how much space needs to be added. In this case, you must create a larger image in step #3.
  5. Start your VM. There may be some disk errors related to the stored block lengths. fsck should be able to automatically fix them. If virt-resize created an extra partition, you can now use a partition editor to delete it and add the space to another partition.
  6. Once you have verified that the VM is working as expected, you can safely remove the old image.

This article is a reference to the original article at: https://maunium.net/blog/resizing-qcow2-images/

Reset a Granstream GXP21xx phone without the menu

Pull the power cord and re-plug it.
When the phone says “booting” hold the 1 and the 9 keys and keep holding until the phone says Factory Reset and asks for the admin password.
To enter the password, you will need to press a key multiple times to get the character you want, such as “ABC1abc” you would press 1 several times to get to get to the small ‘b’.

Password: Grandstr3am

Press the large DOT key in the middle of the arrow keys.
Phone should reboot and re-program itself.