newspaint

Documenting Problems That Were Difficult To Find The Answer To

Monthly Archives: September 2018

Bunnings 12V Garden Spotlight With LED Globe

Bunnings sell a “HPM” brand 12V 5W garden spotlight with a halogen bulb for $5.80 as of writing this article.

Bunnings HPM 12V 5W garden light

Bunnings HPM 12V 5W garden light

I bought several of these along with a “HPM” brand 12V 60W transformer. It should be noted that the transformer outputs AC (alternating current), not DC (direct current).

I wanted to replace the halogen bulb with a LED bulb. I bought a 2-pack from Coles. They were 12V 6W 500 lumens bulbs of form type GU5.3.

Coles GU5.3 12V 6W 500 lumen bulb 2-pack

Coles GU5.3 12V 6W 500 lumen bulb 2-pack

First I had to pry off the front clear plastic pane – I used a knife to do this to lever against the black case around all sides until the cover came lose and could be pulled off.

Front clear cover pried off

Front clear cover pried off

Next I pulled the halogen bulb from the socket.

Halogen bulb removed from GU5.3 socket

Halogen bulb removed from GU5.3 socket

Then I prepared to insert the Coles LED bulb into the socket.

Coles GU5.3 12V bulb ready to be inserted into socket

Coles GU5.3 12V bulb ready to be inserted into socket

After inserting the LED bulb into the socket I actually drilled some holes underneath (not shown here) to improve ventilation. And then snapped the clear plastic cover back on the front.

Clear plastic cover snapped back into place

Clear plastic cover snapped back into place

The light being emitted is significantly stronger than that of the original halogen bulb. But it is worthwhile considering the risk of operating a LED bulb in an enclosed space which is generally not recommended.

Dovecot v2.3.2.1 and Solr v7.4.0

I found the instructions for getting Solr full-text searching (FTS) working with Dovecot rather difficult to follow.

I started off by downloading the latest build of Dovecot (v2.3.2.1 as of this article) because the Ubuntu build of dovecot (v2.2.2) does not have the solr plugin compiled,

After extracting the dovecot sources I ran the following commands to create a build:

$ sudo apt-get install clang-6.0 libmysqlclient-dev libexpat1-dev libssl-dev libsqlite3-dev

$ ./configure --prefix=/opt/dovecot-2.3.2.1 -with-solr --with-mysql --with-ssl=openssl --with-sqlite
$ nice make
$ sudo make install

For Solr I had to install a Java runtime:

$ sudo apt-get install openjdk-9-jre

After installing Solr and getting it running I ran the following command to create a core specifically for dovecot:

$ sudo -u solr -- bin/solr create_core -c dovecot

I had installed Solr in /opt/solr so the next thing I did was delete /opt/solr/server/solr/dovecot/conf/managed-schema and copied the dovecot-2.3.2.1/doc/solr-schema.xml file from the dovecot source to /opt/solr/server/solr/dovecot/conf/schema.xml and changing owner to solr:solr.

Then I had to force a reload of the Solr core, but there were problems.

The following substitutions were necessary in managed-schema (which is what the schema.xml file gets converted to on a reload of the core in Solr):

  • s/”text”/”text_general”/
  • s/”boolean”/”booleans”/
  • s/”plong”/”plongs”/

Then I had to comment out the following blocks in solrconfig.xml:

<!--
    <lst name="typeMapping">
      <str name="valueClass">java.util.Date</str>
      <str name="fieldType">pdates</str>
    </lst>
-->

<!--
    <lst name="typeMapping">
      <str name="valueClass">java.lang.Number</str>
      <str name="fieldType">pdoubles</str>
    </lst>
-->

I updated my /etc/dovecot/dovecot.conf:

mail_plugins = $mail_plugins fts fts_solr zlib

protocol imap {
  mail_plugins = $mail_plugins imap_zlib
}

plugin {
  fts = solr
  fts_solr = url=http://127.0.0.1:8983/solr/dovecot/ break-imap-search
  fts_autoindex=yes
  fts_autoindex_max_recent_msgs=5000
  fts_index_timeout=120
}

Finally I set up some cron jobs to ensure that Solr commits were conducted on a regular basis, an “optimize” was run every so often, and a re-index was done every so often:

*/5 * * * * ubuntu wget -O - 'http://127.0.0.1:8983/solr/dovecot/update?commit=true'
43 1,13 * * * ubuntu wget -O - 'http://127.0.0.1:8983/solr/dovecot/update?optimize=true'

37 * * * * root /opt/dovecot-2.3.2.1/bin/doveadm -c /etc/dovecot/dovecot.conf -v index -u "*" -n 20000 "*"

Hairpin for LXC Containers Using IPTables

Only recently when getting involved with Kubernetes did I discover the term “hairpinning“. It describes something I’d always wanted to do but did not know how.

Let’s say you have a host that has two LXC containers running on it, one of those LXC containers is your e-mail server, the other is a web server:

Example Network That Needs Hairpinning

Example Network That Needs Hairpinning

You might have an IPTables configuration file like the following (if you’re using Ubuntu and have the netfilter-persistent and iptables-persistent packages installed):

###############################################################################
# iptables IPv4 rules for reload on start-up
#
# To Reload:   
#   service netfilter-persistent restart
#
# To Test:
#   iptables-restore -t </etc/iptables/rules.v4
###############################################################################

*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]

# predefine chains
:nat_incoming_tcp - [0:0]

# redirect incoming TCP traffic to chain to NAT to LXC container
-A PREROUTING -i eth+ -p tcp -j nat_incoming_tcp

# NAT for LXC container "email" at 10.0.5.14
-A nat_incoming_tcp -p tcp --dport 25 -j DNAT --to-destination 10.0.5.14:25 -m comment --comment "SMTP"

# NAT for LXC container "web" at 10.0.5.15
-A nat_incoming_tcp -p tcp --dport 80 -j DNAT --to-destination 10.0.5.15:80 -m comment --comment "HTTP"

COMMIT

So far so good – if traffic from the Internet hits your host on 203.0.113.44 port 25 it will be DNAT’d (destination NAT’d) to the email LXC container. And if traffic from the Internet hits your host on 203.0.113.44 port 80 it will be DNAT’d to the web container.

Now – what happens if your web server wants to send an e-mail to yourself? You could program your web server to send all e-mails to 10.0.5.14, the IP address of the LXC container.

However what if your web server wants to send you an e-mail at your external Internet IP address (203.0.113.44)? It might want to do this because it automatically looked up your domain name and was told to contact your external IP address. It’s a problem. If your container tried to contact your external IP address it would send the packet out the lxcbr0 interface (default gateway) and then it might be sent out to the Internet by the server’s default gateway (eth0) – but it would more likely be gobbled as a Martian packet.

The answer is “hairpinning”. The following diagram illustrates the packet flow from a LXC container to another via the external IP address:

Using Hairpin to DNAT Internal Packet to External IP

Using Hairpin to DNAT Internal Packet to External IP

By adding some IPTables rules to the NAT table we can ensure that not only are packets destined for the external IP address NAT’d but they are also masqueraded so that replies follow a healthy path. Note that masquerading can only occur at the POSTROUTING step – so we have to mark the packets coming in from lxcbr0 destined for the external IP address in the PREROUTING step.

You might ask – why do hairpinned packets need to be masqueraded as they go back through the lxcbr0 interface? Consider the “from” address of a packet that gets hairpinned. A packet from the web server would have a “from” address of 10.0.5.15 and a “to” address of 203.0.113.44 initially. After the hairpin the packet would still have a “from” address of 10.0.5.15 and a “to” address of 10.0.5.14. The mail server replies “to” 10.0.5.15 “from” 10.0.5.14. This packet correctly returns to the web server – but the web server doesn’t know anything about a packet “from” 10.0.5.14 – it is expecting to receive a reply from the external IP address of 203.0.113.44! Thus we need to masquerade and force the reply to return to the lxcbr0 interface so the host can use connection tracking to rewrite the addresses and return the reply back from where it came.

# Hairpin
# http://ipset.netfilter.org/iptables-extensions.man.html
-A PREROUTING -i lxcbr+ -p tcp -d 203.0.113.44 -j MARK --set-mark 0x200/0x200
-A PREROUTING -i lxcbr+ -p tcp -d 203.0.113.44 -j nat_incoming_tcp
-A POSTROUTING -o lxcbr+ -m mark --mark 0x200 -j MASQUERADE

Note that because we had a custom chain (“nat_incoming_tcp”) to DNAT packets destined for web or email from the Internet – we can re-use this exact chain for traffic coming in from the LXC bridge interface (lxcbr0) as well.

The rules all together look like:

###############################################################################
# iptables IPv4 rules for reload on start-up
#
# To Reload:   
#   service netfilter-persistent restart
#
# To Test:
#   iptables-restore -t </etc/iptables/rules.v4
###############################################################################

*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]

# predefine chains
:nat_incoming_tcp - [0:0]

# redirect Internet TCP traffic to chain to NAT to appropriate LXC container
-A PREROUTING -i eth+ -p tcp -j nat_incoming_tcp

##################
# Hairpin from LXC
##################
# http://ipset.netfilter.org/iptables-extensions.man.html
-A PREROUTING -i lxcbr+ -p tcp -d 203.0.113.44 -j MARK --set-mark 0x200/0x200
-A PREROUTING -i lxcbr+ -p tcp -d 203.0.113.44 -j nat_incoming_tcp
-A POSTROUTING -o lxcbr+ -m mark --mark 0x200 -j MASQUERADE

###############
# LXC NAT rules
###############
# NAT for LXC container "email" at 10.0.5.14
-A nat_incoming_tcp -p tcp --dport 25 -j DNAT --to-destination 10.0.5.14:25 -m comment --comment "SMTP"

# NAT for LXC container "web" at 10.0.5.15
-A nat_incoming_tcp -p tcp --dport 80 -j DNAT --to-destination 10.0.5.15:80 -m comment --comment "HTTP"

COMMIT

Android ICS Calendar Appointment Import – Unable to Launch Event

This error, “Unable to launch event”, is often encountered when attempting to open an .ics calendar appointment file from Firefox (e.g. from the “Your Downloads” screen).

Typically you would select an .ics file from the list of files you’ve downloaded:

Select .ics file to open and choose to "Open with Calendar"

Select .ics file to open and choose to “Open with Calendar”

and this would give you the option to “Open with Calendar” to which you might choose “JUST ONCE”.

This would result in the error “Unable to launch event” as per the following screenshot:

Firefox warns "Unable to launch event"

Firefox warns “Unable to launch event”

The Workaround

You can still import your .ics file into Calendar!

Go to your applications list, and choose “Files” (on LineageOS), “My Files” (on Samsung), or whatever your generic file explorer is on your phone. Navigate to your “Downloads” folder. Then open the .ics file from there.