diff --git a/README.md b/README.md
index 55830fb..2461157 100644
--- a/README.md
+++ b/README.md
@@ -19,73 +19,29 @@ General Public License, see [below](#license)
 Contents
 ========
 This repository contains the following scripts:
-  * [users2freeipa.py](#users2freeipa)
-    is a migration script to transfer/synchronize LDAP users to/with FreeIPA
   * [freeipa-dns.py](#freeipadns)
     is a script providing functionality not available in FreeIPA itself to
     migrate/synchronize and maintain DNS zones in FreeIPA
   * [freeipa-letsencrypt.sh](#freeipaletsencrypt)
     is a script to setup and configure Certbot and FreeIPA to request and renew
     use publicly verifiable Let's Encrypt certificate(s)
-
-
-<a name=users2freeipa>users2freeipa.py</a>
----------------------------------------------
-This script uses LDAP to obtain users from a MacOS Server (or other LDAP)
-server and synchronizes the results with the users registered in FreeIPA.
-Since it synchronizes data it is safe to run multiple times and users can be
-imported also as stage users initially.
-
-The intent is to migrate user data and to not drag on a legacy setup. For
-this reason, the script will create new user and group IDs and not copy homedir
-and shell information by default. For the IDs, the legacy information can be
-stored in an FreeIPA ID View so it remains available, other items can be copied
-over using command line options. Passwords can be copied-over (if available in
-a usable format), and the script also supports having FreeIPA generate random
-passwords and store these in a file for further processing/sharing with users.
-
-Users can be copied from an existing (generic) LDAP database and a MacOS Server
-OpenDirectory-flavor LDAP server. In this case, additional information (e.g.
-Apple's generatedUID) will be copied over as well. Please note that this does
-require customizing the FreeIPA LDAP schema, which the script will check for
-and can install (option ```-U```). As the setup is modular it should be easy
-to tweak or add other migrations.
-
-By default all users will be migrated/synchronized, but it is also possible to
-limit this to specific user(s) or group(s) or specifically exclude specific
-users or groups. An example to copy all users in the group ```workgroup```
-except ```admin``` from an Apple MacOS OpenDirectory server:
-~~~
-./users2freeipa.py -v -O -U -c "Legacy LDAP" -g workgroup -x admin -G \
-                   -P -p passwords.txt ldap://ldap.mydomain.tld
-~~~
-This will also install the OpenDirectory-specific schema customization, create
-groups and copy group memberships, copy usuable passwords and ensure that all
-users have a password (storing generated passwords to ```passwords.txt```)
-
-Please note that migrating existing passwords from LDAP has limitations, see
-[this](https://www.freeipa.org/page/NIS_accounts_migration_preserving_Passwords)
-page on migrating NIS passwords and [this](https://pagure.io/freeipa/issue/4732)
-issue reported with it. Bottom line is that (at this moment) password migration
-is flawed and always will require manual action from the user. For this reason
-the better alternative to set a random password and ask the user to reset the
-password using the FreeIPA portal makes more sense.
-
-Before running a production user migration, it is important to have FreeIPA
-setup and configured correctly so that the right defaults are used for new
-users. Best is to start with a single user and add that as a stage user (please
-note that this will not yet assign userIDs, group memberships and a password
-as FreeIPA does not yet support that) and use an ID View to store legacy data.
-
-For all available command-line options, run ```users2freeipa.py -h```
+  * [set-dns-source.sh](#setdnssource)
+    enforce the source address of outgoing DNS messages using firewalld as work
+    around for bind-dyndb-ldap plugin not supporting bind's ```notify-source```
+  * [users2freeipa.py](#users2freeipa)
+    is a migration script to transfer/synchronize LDAP users to/with FreeIPA
 
 
 <a name=freeipadns>freeipa-dns.py</a>
-----------------------------------------------------------------
+-------------------------------------
 This script provides functionality not provided by FreeIPA to migrate and/or
 synchronize / maintain DNS data in FreeIPA. Currently the following commands
 are implemented:
-  * axfr - import/synchronize a DNS zone in FreeIPA using a zone-xfer.
+  * axfr - synchronize DNS zone(s) using a zone-xfer. Contrary to the suggested
+    [migration approach](https://docs.pagure.org/bind-dyndb-ldap/Migration.html)
+    this uses the FreeIPA API to migrate or synchronize DNS zones with FreeIPA
+    so it can also be used for running things in parallel or gradual migrations.
+
     for example, to migrate / synchronize fromain ```domain.tld``` from DNS
     server ```192.168.1.53``` without checking DNS overlap, issue the command:
 
@@ -172,7 +128,7 @@ the available options for each commmand run ```freeipa-dns.py <command> -h```
 
 
 <a name=freeipaletsencrypt>freeipa-letsencrypt.sh</a>
-----------------------------------------------------------------
+-----------------------------------------------------
 This script will ensure the necessary setup is in place so that Certbot (EFF's
 certificate request script for Let's Encrypt) will work with FreeIPA for DNS
 challenges and and instructs it to deploy new certificates for FreeIPA's web
@@ -202,9 +158,9 @@ by setting one of the following environment variables:
 
 | Variable    | Description                        | Default value             |
 |-------------|------------------------------------|---------------------------|
-| CERTNAME    | certificate hostname,              | host's canonicalname  (*) |
-| DNSALTNAMES | certificate DNS names              | host's principalnames (*) |
-| DOMAIN      | Let's Encrypt challenge DNS zone   | {DNS name's domain}  (**) |
+| CERTNAME    | certificate hostname,              | host's canonicalname  (1) |
+| DNSALTNAMES | certificate DNS names              | host's principalnames (1) |
+| DOMAIN      | Let's Encrypt challenge DNS zone   | {DNS name's domain}  (2) |
 | EMAIL       | administrator's e-mail address     | hostmaster@{domain}       |
 | HOSTNAME    | FreeIPA server's hostname          | `hostname --fqdn`         |
 | KEYTAB      | Let'sEncrypt service's keytab file | /etc/letsencrypt/keytab   |
@@ -214,11 +170,86 @@ by setting one of the following environment variables:
 | SUDO        | command to become root (if needed) | sudo                      |
 | TMPDIR      | Directory for temporary files      | /tmp                      |
 
-(*)  obtained from the FreeIPA server record looked up based on ${HOSTNAME}
-(**) this allows to enforce the DNS zone, e.g. host.subdomain in mydomain.tld
+(1)  obtained from the FreeIPA server record looked up based on ${HOSTNAME}
+(2) this allows to enforce the DNS zone, e.g. host.subdomain in mydomain.tld
 
 When things change, the script can simply be run again.
 
+
+<a name=setdnssource>set-dns-source.sh</a>
+------------------------------------------
+FreeIPA's bind-dyndb-ldap plugin does not support bind's ```notify-source```
+settings and simply uses the main address when sending DNS notifications. This
+breaks multi-homed setups and, in case of IPv6, even causes bind to send NOTIFY
+messages from the temporary IPv6 address, causing slave servers to reject them.
+This script will setup Source NAT in firewalld to enforce the IPv4/IPv6 address
+of outgoing DNS packets to ensure that DNS NOTIFYs messages will use the correct
+source IPv4/IPv6 address. The IPv4/IPv6 address(es) to enforce should either be
+provided in the environment or changed at the top of the script. In case an IPv4
+address is provided, the script can figure out itself which device to use when
+running it, if not this should be provided as well. To install run:
+~~~
+sudo IPV4ADDR=192.168.0.100 IPV6ADDR=none ./set-dns-source.sh install
+~~~
+to remove installed rules, run with the same parameters and parameter 'remove':
+~~~
+sudo IPV4ADDR=192.168.0.100 IPV6ADDR=none ./set-dns-source.sh remove
+~~~
+and to see custom rules run: ```sudo firewall-cmd --direct --get-all-rules```
+
+
+
+<a name=users2freeipa>users2freeipa.py</a>
+------------------------------------------
+This script uses LDAP to obtain users from a MacOS Server (or other LDAP)
+server and synchronizes the results with the users registered in FreeIPA.
+Since it synchronizes data it is safe to run multiple times and users can be
+imported also as stage users initially.
+
+The intent is to migrate user data and to not drag on a legacy setup. For
+this reason, the script will create new user and group IDs and not copy homedir
+and shell information by default. For the IDs, the legacy information can be
+stored in an FreeIPA ID View so it remains available, other items can be copied
+over using command line options. Passwords can be copied-over (if available in
+a usable format), and the script also supports having FreeIPA generate random
+passwords and store these in a file for further processing/sharing with users.
+
+Users can be copied from an existing (generic) LDAP database and a MacOS Server
+OpenDirectory-flavor LDAP server. In this case, additional information (e.g.
+Apple's generatedUID) will be copied over as well. Please note that this does
+require customizing the FreeIPA LDAP schema, which the script will check for
+and can install (option ```-U```). As the setup is modular it should be easy
+to tweak or add other migrations.
+
+By default all users will be migrated/synchronized, but it is also possible to
+limit this to specific user(s) or group(s) or specifically exclude specific
+users or groups. An example to copy all users in the group ```workgroup```
+except ```admin``` from an Apple MacOS OpenDirectory server:
+~~~
+./users2freeipa.py -v -O -U -c "Legacy LDAP" -g workgroup -x admin -G \
+                   -P -p passwords.txt ldap://ldap.mydomain.tld
+~~~
+This will also install the OpenDirectory-specific schema customization, create
+groups and copy group memberships, copy usuable passwords and ensure that all
+users have a password (storing generated passwords to ```passwords.txt```)
+
+Please note that migrating existing passwords from LDAP has limitations, see
+[this](https://www.freeipa.org/page/NIS_accounts_migration_preserving_Passwords)
+page on migrating NIS passwords and [this](https://pagure.io/freeipa/issue/4732)
+issue reported with it. Bottom line is that (at this moment) password migration
+is flawed and always will require manual action from the user. For this reason
+the better alternative to set a random password and ask the user to reset the
+password using the FreeIPA portal makes more sense.
+
+Before running a production user migration, it is important to have FreeIPA
+setup and configured correctly so that the right defaults are used for new
+users. Best is to start with a single user and add that as a stage user (please
+note that this will not yet assign userIDs, group memberships and a password
+as FreeIPA does not yet support that) and use an ID View to store legacy data.
+
+For all available command-line options, run ```users2freeipa.py -h```
+
+
 <a name="license">License</a>
 -----------------------------
 These scripts, documentation & configration examples are free software: you can
diff --git a/freeipa-letsencrypt.sh b/freeipa-letsencrypt.sh
index b7b610c..c6066cd 100755
--- a/freeipa-letsencrypt.sh
+++ b/freeipa-letsencrypt.sh
@@ -36,7 +36,13 @@ else
 fi
 
 # Set KRB5CCNAME to ensure the current ticket cache will be used
-KRB5CCNAME=${KRB5CCNAME:-$(klist -l | head -3 | tail -1 | cut -d\  -f2-)}
+: ${KRB5CCNAME:=$(klist -l | head -3 | tail -1 | cut -d\  -f2-)}
+
+# Set parameters
+: ${CERTNAME:=$(ipa host-show $HOSTNAME --raw | fgrep "krbcanonicalname: host/" | cut -d/ -f2 | cut -d@ -f1)}
+: ${DNSALTNAMES:=$(ipa host-show $HOSTNAME --raw | fgrep "krbprincipalname: host/" | cut -d/ -f2 | cut -d@ -f1 | paste -sd,)}
+: ${EMAIL:=hostmaster@${HOSTNAME#*.}}
+: ${SERVICE:=letsencrypt/$(ipa host-show $HOSTNAME --raw | fgrep "krbcanonicalname: host/" | cut -d/ -f2)}
 
 # Ensure the user consents with changing his system.
 if tty > /dev/null; then
@@ -46,12 +52,11 @@ use a Let's Encrypt certificate and will automatically renew that when needed.
 The following changes will be made for this:
   1. Add Let's Encrypt Root and Intermediate CAs as trusted CAs
   2. Create DNS Administrator role in FreeIPA that can edit any DNS Record
-  3. Create host service: ${SERVICE:=letsencrypt/$(
-ipa host-show $HOSTNAME --raw | fgrep "krbcanonicalname: host/" | cut -d/ -f2)}
+  3. Create host service: $SERVICE
   4. Allow letsencrypt host service to manage DNS entries
-  5. Register with Let's encrypt as: ${EMAIL:=hostmaster@${HOSTNAME#*.}}
-  6. Request a Let's Encrypt SSL certificate for: ${CERTNAME:=$(ipa host-show $HOSTNAME --raw | fgrep "krbcanonicalname: host/" | cut -d/ -f2 | cut -d@ -f1)}
-     with DNS Alternative names: ${DNSALTNAMES:=$(ipa host-show $HOSTNAME --raw | fgrep "krbprincipalname: host/" | cut -d/ -f2 | cut -d@ -f1 | paste -sd,)}
+  5. Register with Let's encrypt as: $EMAIL
+  6. Request a Let's Encrypt SSL certificate for: $CERTNAME
+     with DNS Alternative names: $DNSALTNAMES
   7. install the Let's Encrypt certificate in apache as host SSL certificate,
      storing renewal config in: /etc/letsencrypt/renewal/$HOSTNAME.conf
   8. configure the Fedora Certbot renew timer so that certbot is run daily to
@@ -121,7 +126,7 @@ $SUDO systemctl enable --now certbot-renew.timer
 
 cat << EOT
 
-FreeIPA was successfully setup to use a Let\'s Encrypt certificate for its web
+FreeIPA was successfully setup to use a Let's Encrypt certificate for its web
 interface. This certificate will be renewed automatically when needed.
 
 EOT
diff --git a/set-dns-source.sh b/set-dns-source.sh
new file mode 100755
index 0000000..e9e3d6f
--- /dev/null
+++ b/set-dns-source.sh
@@ -0,0 +1,48 @@
+#!/bin/bash -e
+#
+# set-dns-source.sh - Setup Source NAT in firewalld for outgoing DNS traffic
+#
+# Version 1.0, latest version, documentation and bugtracker available at:
+#		https://gitlab.lindenaar.net/scripts/freeipa
+#
+# Copyright (c) 2018 Frederik Lindenaar
+#
+# This script is free software: you can redistribute and/or modify it under the
+# terms of version 3 of the GNU General Public License as published by the Free
+# Software Foundation, or (at your option) any later version of the license.
+#
+# This script is distributed in the hope that it will be useful but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program.  If not, visit <http://www.gnu.org/licenses/> to download it.
+
+case $1 in
+  install)      CMD=add
+                ;;
+  remove)       CMD=remove
+                ;;
+  *)            echo "usage: $0 <install | remove>"
+                exit 1
+esac
+
+IPV4ADDR=${IPV4ADDR:?Please provide an IPv4 address or set to 'none'}
+IPV6ADDR=${IPV6ADDR:?Please provide an IPv6 address or set to 'none'}
+
+DEV=${DEV:=$( /usr/sbin/ip route | fgrep ${IPV4ADDR:?No IPv4 address provided, please set device manually} | cut -d\  -f3 )}
+: ${DEV:?No route found for $IPV4ADDR, please check config or set device manually}
+
+# inspired by https://blog.sebastien.raveau.name/2009/04/per-process-routing.html
+# and https://unix.stackexchange.com/questions/389756/how-to-use-snat-with-firewalld-vs-masq
+
+for PROTO in ipv4 ipv6; do
+  [ "$PROTO" == ipv6 ] && ADDR="$IPV6ADDR" || ADDR="$IPV4ADDR"
+  if [ -n "$ADDR" -a "$ADDR" != none ]; then
+    for MODE in "" --permanent; do
+      firewall-cmd $MODE --direct --$CMD-rule $PROTO mangle OUTPUT 0 -m owner --uid-owner named -j MARK --set-mark 53
+      firewall-cmd $MODE --direct --$CMD-rule $PROTO nat POSTROUTING 0 -o $DEV -m mark --mark 53 -j SNAT --to-source $ADDR
+    done
+  fi
+done
+