Category: BSD

  • Add routing to L2TP VPN in Mac OS X

    L2TP over IPSec is available in MAC OS X, and is very stable in Ventura with OpenBSD server. However, if your network is in the same subnet as the remote network you’re reaching with the VPN is tricky. Let me try to explain:

    me (with home network 192.168.1.0/24) —- L2TP VPN with IP 10.0.0.2 —– Internet —— Office L2TP VPN with 10.0.0.1 gateway —- Office network 192.168.1.0/24 {some machines you want to reach 192.168.1.9 and 192.168.1.124 for example}

    Now, when you establish the VPN, you can ping 10.0.0.1 from your laptop at home, but you can not ping 192.168.1.9 on the other side of the VPN (my office network).

    The easiest way is to add these routes in the point-to-point config in Mac OS.

    1. Open a shell and go to /etc/ppp directory
    # cd /etc/ppp
    2. Create a file called ip-up with:
    # sudo nano ip-up
    3. Put inside these additional routings you want to pop-up when you establish the VPN:
    #!/bin/sh
    /sbin/route add 192.168.1.116/32 -interface ppp0
    /sbin/route add 192.168.1.117/32 -interface ppp0
    /sbin/route add 192.168.1.124/32 -interface ppp0
    4. Exit and save.

    Now, when a VPN is setup, these 3 routes 192.168.1.116, .117, .124 will be available thru the VPN interface ppp0 (the default in Mac Os X).

    How easy it is to make an OpenBSD L2TP VPN server? Very easy, just need to touch three files 🙂

    Let’s first enable IPSEC and ISAKMPD on the OpenBSD box:
    # rcctl enable ipsec
    # rcctl enable isakmpd
    # rcctl set isakmpd flags -K

    In OpenBSD 7.2, all you need to do is:

    1. In /etc/npppd folder open the npppd-users file and add:
    dilyan:\
    :password=123456:
    This will add user “dilyan” with password “123456”

    2. In the same directory, you need to to touch the npppd.conf file to configure DNS, IP addresses and listening ports, etc:

    authentication LOCAL type local {
    users-file “/etc/npppd/npppd-users”
    }

    tunnel L2TP protocol l2tp {
    listen on 0.0.0.0
    listen on ::
    }

    ipcp IPCP {
    pool-address 10.0.0.2-10.0.0.254
    dns-servers 192.168.1.9 8.8.8.8
    }

    interface pppx0 address 10.0.0.1 ipcp IPCP
    bind tunnel from L2TP authenticated by LOCAL to pppx0

    with this basically we’re saying – listen on the host for IPv4 and v6, have a gateway address of 10.0.0.1, assign to the coming connections addresses from 10.0.0.2 till 254, and use DNSs 192.168.1.9 and 8.8.8.8.

    3. The last is to touch /etc/ipsec.conf with adding the following text:
    ike passive esp tunnel from X.Y.Z.Q to any \
    main group “modp1024” \
    quick group “modp1024” \
    psk “0987654”

    where X.Y.Z.Q is the public IP address of the VPN server, and 0987654 is the password for the tunnel (the shared secret).

    In Mac OS X, the L2TP over IPSec is in the default VPN configurations (System Setting -> VPN -> Add VPN Configuration), add the server address (the X.Y.Z.Q from the step above), user authorization is “Password” and put the 123456 from the npppd configuration, the Machine Authentication shall be chose as “Shared Secret” and is the 0987654 one you put in ipsec.conf. Voila.

    More details in the OpenBSD FAQ: https://www.openbsd.org/faq/faq17.html

  • WordPress installation on FreeBSD 13.1 particularities

    There’s a little specific when installing WordPress from package under FreeBSD 13 and its Apache.

    Now, the Apache server coming with the distro is v. 2.4.54 and it is expecting PHP 8.0 (otherwise loading some modules is not working like msqli).
    If you install WordPress from packages it will come with v.6.1 and it has dependencies on PHP 8.1, and then a little drama is starting as Apache can not loading all the needed modules and the error log is full of issues.
    It becomes a nightmare, so the easiest way I have found is to do it by hand (no from packages):

    1. De-install WordPress from the FreeBSD repository and PHP 8.1
    2. Install PHP 8.0 from packages and add php80-zlib + php80-filter, then enable the service:
    # pkg install mod_php80 php80-zlib php80-filter
    # cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini
    # service php-fpm enable
    # service php-fpm start
    3. You need to add the following either in the httpd.conf, or create a new modules file, or example – /usr/local/etc/apache24/modules.d/001_mod-php.conf. Then add the following text:

    DirectoryIndex index.php index.html

    SetHandler application/x-httpd-php


    SetHandler application/x-httpd-php-source


    4. Touch the Apache config file, which in FreeBSD 13.1 is located at /usr/local/etc/apache24/httpd.conf
    a) make sure the following like is uncommented and is there: LoadModule rewrite_module libexec/apache24/mod_rewrite.so
    b) point the document root to the right directory of the WordPress, in my case it is under: /usr/local/www/wordpress. So, httpd.conf is having:
    DocumentRoot “/usr/local/www/wordpress”

    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted

    5. Download the latest WordPress version (as of writing this is 6.2) and unzip it in the directory /usr/local/www/wordpress:
    # wget https://wordpress.org/latest.tar.gz
    # tar -xzvf latest.tar.gz
    6. Restart all the services and open the IP address of the configured Apache:
    # service apache24 restart

  • For few msec less – local Unbound DNS

    It is always the DNS!

    I have several jails and virtual machines on my Dell T5600 home lab. It is much easier to operate when each machine is having a FQDM, so I decided to play with Unbound DNS which is a kind of default for OpenBSD and FreeBSD.
    Here is the setup – the host OS is FreeBSD 13.1 (in the example below with IP 192.168.1.115), OpenBSD 7.2 (IP 192.168.1.9) is a virtual machine with bhyve on top of the host OS.

    I have configured all my hosts with a domain name under *.dilyan.be + the reverse record. Below you’ll see in the example postgres.dilyan.be, openbsd.dilyan.be, wp.dilyan.be, etc with their addresses configured.

    In OpenBSD you just have to enable it:

    # rcctl enable unbound
    # rcctl start unbound
    unbound(ok)

    the config files are under /var/unbound/etc

    here’s my config:


    [root@openbsd etc]$ cat unbound.conf
    # $OpenBSD: unbound.conf,v 1.21 2020/10/28 11:35:58 sthen Exp $
    server:
    interface: 127.0.0.1
    interface: 192.168.1.9
    interface: ::1
    port: 53
    access-control: 0.0.0.0/0 refuse
    access-control: 127.0.0.0/8 allow
    access-control: ::0/0 refuse
    access-control: ::1 allow
    access-control: 10.0.0.0/8 allow
    access-control: 127.0.0.0/8 allow
    access-control: 192.168.0.0/16 allow
    root-hints: "/var/unbound/db/root.hints"
    hide-identity: yes
    hide-version: yes
    auto-trust-anchor-file: "/var/unbound/db/root.key"
    val-log-level: 2
    aggressive-nsec: yes
    verbosity: 1
    harden-glue: yes
    harden-dnssec-stripped: yes
    use-caps-for-id: yes
    do-ip4: yes
    do-ip6: yes
    do-udp: yes
    do-tcp: yes
    cache-min-ttl: 3600
    cache-max-ttl: 86400
    prefetch: yes
    num-threads: 2
    msg-cache-slabs: 8
    rrset-cache-slabs: 8
    infra-cache-slabs: 8
    key-cache-slabs: 8
    rrset-cache-size: 512m
    msg-cache-size: 256m
    so-rcvbuf: 2m
    private-address: 172.16.0.0/12
    private-domain: "dilyan.be"
    unwanted-reply-threshold: 10000
    val-clean-additional: yes
    statistics-cumulative: yes
    extended-statistics: yes
    use-syslog: yes
    local-zone: "dilyan.be" static
    local-data: "dilyan.be IN A 52.208.215.96"
    local-data: "www.dilyan.be IN A 52.208.215.96"
    local-data: "vpn.dilyan.be IN A 212.5.153.206"
    local-data: "django.dilyan.be IN A 192.168.1.119"
    local-data: "mongodb.dilyan.be IN A 192.168.1.118"
    local-data: "test.dilyan.be IN A 192.168.1.120"
    local-data: "wp.dilyan.be IN A 192.168.1.116"
    local-data: "postgres.dilyan.be IN A 192.168.1.117"
    local-data: "neo4j.dilyan.be IN A 192.168.1.121"
    local-data: "rpi.dilyan.be IN A 192.168.0.115"
    local-data: "wiki.dilyan.be IN A 192.168.1.124"
    local-data: "openbsd.dilyan.be IN A 192.168.1.9"
    local-data: "freebsd.dilyan.be IN A 192.168.1.115"
    local-data: "obsd.dilyan.be IN A 192.168.1.223"
    local-data-ptr: "192.168.1.119 django.dilyan.be"
    local-data-ptr: "192.168.1.118 mongodb.dilyan.be"
    local-data-ptr: "192.168.1.120 test.dilyan.be"
    local-data-ptr: "192.168.1.116 wp.dilyan.be"
    local-data-ptr: "192.168.1.117 postgres.dilyan.be"
    local-data-ptr: "192.168.1.121 neo4j.dilyan.be"
    local-data-ptr: "192.168.0.115 rpi.dilyan.be"
    local-data-ptr: "192.168.1.124 wiki.dilyan.be"
    local-data-ptr: "192.168.1.9 openbsd.dilyan.be"
    local-data-ptr: "192.168.1.115 freebsd.dilyan.be"
    local-data-ptr: "192.168.1.223 obsd.dilyan.be"
    forward-zone:
    name: .
    forward-addr: 8.8.8.8 #Google-1
    forward-addr: 1.1.1.1 #Cloudflare-1
    forward-addr: 9.9.9.9 #Quad9.net
    forward-addr: 1.0.0.1 #Cloudflare-2
    forward-addr: 8.8.4.4 #Google-2
    forward-addr: 149.112.112.112 #Quad9-2
    forward-addr: 208.67.222.222 #OpenDNS-1
    forward-addr: 208.67.220.220 #OpenDNS-2
    remote-control:
    control-enable: yes
    control-interface: /var/run/unbound.sock

    After completing the config, restart the service with

    # rcctl restart unbound
    unbound(ok)

    So, what do I gain, apart from having the local machines with DNS? Well, a couple of milliseconds :).
    Here’re are some tests from the local machine compared to Google, Cloudflare, Quad. When asking for the IP address of bbc.co.uk, Cloudflare replied in 5 msec, Google in 31 msec, the local OpenBSD in 2 ms.

    [root@openbsd etc]$ drill bbc.co.uk @1.1.1.1

    ;; HEADER;- opcode: QUERY, rcode: NOERROR, id: 33177
    ;; flags: qr rd ra ; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
    ;; QUESTION SECTION:
    ;; bbc.co.uk. IN A
    ;; ANSWER SECTION:
    bbc.co.uk. 261 IN A 151.101.64.81
    bbc.co.uk. 261 IN A 151.101.128.81
    bbc.co.uk. 261 IN A 151.101.192.81
    bbc.co.uk. 261 IN A 151.101.0.81
    ;; AUTHORITY SECTION:
    ;; ADDITIONAL SECTION:
    ;; Query time: 5 msec
    ;; SERVER: 1.1.1.1
    ;; WHEN: Fri Mar 31 11:53:16 2023
    ;; MSG SIZE rcvd: 91
    ———
    [root@openbsd etc]$ drill bbc.co.uk @8.8.8.8
    ;; HEADER;- opcode: QUERY, rcode: NOERROR, id: 30222
    ;; flags: qr rd ra
    ; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
    ;; QUESTION SECTION:
    ;; bbc.co.uk. IN A
    ;; ANSWER SECTION:
    bbc.co.uk. 21 IN A 151.101.0.81
    bbc.co.uk. 21 IN A 151.101.64.81
    bbc.co.uk. 21 IN A 151.101.128.81
    bbc.co.uk. 21 IN A 151.101.192.81
    ;; AUTHORITY SECTION:
    ;; ADDITIONAL SECTION:
    ;; Query time: 31 msec
    ;; SERVER: 8.8.8.8
;; WHEN: Fri Mar 31 11:53:23 2023
    ;; MSG SIZE rcvd: 91
    ——–
    [root@openbsd etc]$ drill bbc.co.uk @192.168.1.9
    ;; HEADER;- opcode: QUERY, rcode: NOERROR, id: 55555
    ;; flags: qr rd ra
    ; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
    ;; QUESTION SECTION:
    ;; bbc.co.uk. IN A
    ;; ANSWER SECTION:
    bbc.co.uk. 3580 IN A 151.101.128.81
    bbc.co.uk. 3580 IN A 151.101.192.81
    bbc.co.uk. 3580 IN A 151.101.0.81
    bbc.co.uk. 3580 IN A 151.101.64.81
    ;; AUTHORITY SECTION:
    ;; ADDITIONAL SECTION:
    ;; Query time: 2 msec
    ;; SERVER: 192.168.1.9
    ;; WHEN: Fri Mar 31 11:53:27 2023
    ;; MSG SIZE rcvd: 91

    Now, in FreeBSD is a little bit confusing, as they have local_unbound and “normal” unbound. The configs are under /var/unbound, but the structure is a little different than in OpenBSD. For example, there’re different files for forwarders, blocked sites, etc. that are included in the main unbound.conf at the end:


    include: /var/unbound/forward.conf
    include: /var/unbound/lan-zones.conf
    include: /var/unbound/control.conf
    include: /var/unbound/conf.d/*.conf
    include: /var/unbound/blocked_servers

    Then the example from the OpenBSD is identical, just the forwarders (Google, Cloudflare, Quad9 DNS addresses are in the file forward.conf). I also noticed that some of the parameters in the OpenBSD are giving errors, so I had to remove the following lines from the above config to make it work:


    # auto-trust-anchor-file: "/var/unbound/root.key"
    # num-threads: 2
    # rrset-cache-size: 512m
    # msg-cache-size: 256m
    # so-rcvbuf: 2m

    I did not have the time to play and make the FreeBSD options work, just commented them. The rest is identical with the OpenBSD config. Restart the service with:

    #service local_unbound restart

    N.B. local_unbound is different than unbound in FreeBSD!

    Now the test of the drill, from the FreeBSD shell, this time with cnn.com:

    [root@fbsd /var/unbound]# drill cnn.com @1.1.1.1

    ;; HEADER opcode: QUERY, rcode: NOERROR, id: 11433
    ;; flags: qr rd ra ; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
    ;; QUESTION SECTION:
    ;; cnn.com. IN A
    ;; ANSWER SECTION:
    cnn.com. 58 IN A 151.101.195.5
    cnn.com. 58 IN A 151.101.131.5
    cnn.com. 58 IN A 151.101.3.5
    cnn.com. 58 IN A 151.101.67.5
    ;; AUTHORITY SECTION:
    ;; ADDITIONAL SECTION:
    ;; Query time: 2 msec
    ;; SERVER: 1.1.1.1
    ;; WHEN: Fri Mar 31 12:08:20 2023
    ;; MSG SIZE rcvd: 89
    ——–
    [root@fbsd /var/unbound]# drill cnn.com @8.8.8.8
    ;; HEADER opcode: QUERY, rcode: NOERROR, id: 29708
    ;; flags: qr rd ra
    ; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
    ;; QUESTION SECTION:
    ;; cnn.com. IN A
    ;; ANSWER SECTION:
    cnn.com. 18 IN A 151.101.195.5
    cnn.com. 18 IN A 151.101.3.5
    cnn.com. 18 IN A 151.101.131.5
    cnn.com. 18 IN A 151.101.67.5
    ;; AUTHORITY SECTION:
    ;; ADDITIONAL SECTION:
    ;; Query time: 28 msec
    ;; SERVER: 8.8.8.8
    ;; WHEN: Fri Mar 31 12:08:25 2023
    ;; MSG SIZE rcvd: 89
    ——–
    [root@fbsd /var/unbound]# drill cnn.com @192.168.1.115
    ;; HEADER opcode: QUERY, rcode: NOERROR, id: 62215
    ;; flags: qr rd ra
    ; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
    ;; QUESTION SECTION:
    ;; cnn.com. IN A
    ;; ANSWER SECTION:
    cnn.com. 3595 IN A 151.101.131.5
    cnn.com. 3595 IN A 151.101.195.5
    cnn.com. 3595 IN A 151.101.3.5
    cnn.com. 3595 IN A 151.101.67.5
    ;; AUTHORITY SECTION:
    ;; ADDITIONAL SECTION:
    ;; Query time: 0 msec
    ;; SERVER: 192.168.1.115
    ;; WHEN: Fri Mar 31 12:08:37 2023
;; MSG SIZE rcvd: 89

    Cloudflare replied in 2 ms, Google in 28 msec, the FreeBSD in 0 msec .. obviously it was cached 🙂

    To be honest, the FreeBSD is _very_ fast if the DNS is in the cache and has been requested recently. If it is the first time request, it can go to 100 ms, as it asks the forwarders (Google, Cloudflare, Quad9, OpenDNS that I’ve configured). It is normal to see 0 msec for hours after the DNS was cached, something that I’ve never seen in OpenBSD, so looks like the caching mechanisms are different.

    A great how-to with more explanations is https://calomel.org/unbound_dns.html

  • Firewall rules on OpenBSD security bastion

    The setup is like that:

    Internet (public IP) — ISP router — FreeBSD 13.1 host — OpenBSD 7.2 virtual machine

    the OpenBSD is running a) ssh server with Yubikey authorization, b) Wireguard VPN server, c) L2TP VPN as a back-up on the Wireguard. The ISP router is forwarding ports tcp 22 (ssh), tcp 443 (Wireguard), udp 400 and 4500 for the L2TP VPN to the OpenBSD address directly.

    The pf.conf rules to make this setup work:

    [root@openbsd dilyan]$ cat /etc/pf.conf
    set block-policy return
    set limit table-entries 400000 #due to pfbadhost
    set skip on lo
    ext_if = “vio0”
    vpn_if = “pppx”
    vpn_net = “10.0.0.0/24”
    home_net = “192.168.0.0/24” #home network thru VPN
    office_net = “192.168.1.0/24” # office network
    table <bruteforce> persist #table for ssh-attackers
    table <pfbadhost> persist file “/etc/pf-badhost.txt”

    antispoof for { $ext_if, $vpn_if }
    match in all scrub (no-df random-id )

    block return # block stateless traffic
    block quick from <bruteforce> #block the ssh-attackers
    block in quick on egress from <pfbadhost>
    block out quick on egress to <pfbadhost>

    # By default, do not permit remote connections to X11
    block return in on ! lo0 proto tcp to port 6000:6010
    # Port build user does not need network
    block return out log proto {tcp udp} user _pbuild
    block all

    pass # establish keep-state
    pass inet proto icmp synproxy state #allow ICMP protocol – all
    pass proto { tcp, udp } from { wg0:network, $home_net, $vpn_net, $office_net } to port { ssh, domain }
    pass proto { tcp, udp } to port { ssh, 500, 4500 } keep state (max-src-conn 5, max-src-conn-rate 3/60, overload <bruteforce> flush global)
    pass proto udp from {$ext_if, $office_net} to port { 123 } #allow network time protocol (NTP) port

    # Rule for WireGuard VPN to NAT traffic to public net#
    match out on $ext_if from wg0:network to any nat-to $ext_if

    # Rules for L2TP VPN to work and NAT traffic #
    pass on $ext_if proto esp # allow ESP protocol on public interface
    pass on $ext_if proto udp to port { isakmp, ipsec-nat-t } # allow isakmpd UDP traffic through the public interface on ports 500 and 4500
    pass on enc0 keep state (if-bound) # filter all IPSec traffic on the enc interface
    pass on $vpn_if from { $vpn_net, $home_net } # allow all trafic in on and out to the VPN network
    pass on $vpn_if to { $vpn_net, $home_net }
    match out on $ext_if from $vpn_net to any nat-to $ext_if # nat VPN traffic going out on the public interface with the public IP

    These rules will _not_ work on FreeBSD, as their implementation requires grouping the rules in particular order – Macros, Tables, Options, Normalization, NAT/Redirections and then Filtering (i.e. you need to rearrange the rules).

    Once you open port 22 for ssh service on a public IP address, attackers will start attempts like ~17-20k tries per day. This is why I implemented the table, so an IP that tries to guess a username/password more than 3 times per 60 minutes to be blocked for a day. This reduced the attacks to less than 12k per day. Then I followed this how-to https://geoghegan.ca/pfbadhost.html to block malicious IPs thru the table and the attempts dropped below 9k per day.

  • Few specifics in running PostgreSQL, MongoDB, Neo4j and ELK in FreeBSD 13.1 jails

    As a note to myself and to save the time in troubleshooting and chasing issues, few specifics to make the below services run in jail environment under FreeBSD 13.1.

    First, the generic options:
    # cat /etc/jail.conf
    allow.raw_sockets = 1;
    allow.set_hostname = 1;
    allow.sysvipc = 1;
    mount.devfs; # Mount devfs inside the jail
    exec.start = "/bin/sh /etc/rc"; # Start command
    exec.stop = "/bin/sh /etc/rc.shutdown"; # Stop command

    1. PostgreSQL: few parameters need to be set in the jail.conf – sysvshm, sysvsem, sysvmsg
    postgres {
    host.hostname = postgres.dilyan.be; # Hostname
    ip4.addr = 192.168.3.117; # IP address of the jail
    path = "/zroot/jails/postgres"; # Path to the jail
    sysvshm = new;
    sysvsem = new;
    sysvmsg = new;
    }

    2. MongoDB: all it needs is allow.mlock in the jail definition
    mongodb {
    host.hostname = mongodb.dilyan.be; # Hostname
    ip4.addr = 192.168.3.118; # IP address of the jail
    path = "/zroot/jails/mongodb"; # Path to the jail
    allow.mlock;
    }

    3. Neo4j: due to the java you need to specify how to mount the local fstab
    neo4j {

    host.hostname = neo4j.dilyan.be; # Hostname
    ip4.addr = 192.168.3.121; # IP address of the jail
    path = "/zroot/jails/neo4j"; # Path to the jail
    mount.fstab="/zroot/jails/neo4j/etc/fstab.neo4j"; # mount local fstab for the java
    }

    the content of the fstab in the jail is:

    fdesc /dev/fd fdescfs rw 0 0
    proc /proc procfs rw 0 0

    4. Elastic Search and Kibana (ELK stack): same as for the Neo4j – you need to specify how to mount the local fstab


    elk {
    host.hostname = elk.dilyan.be; # Hostname
    ip4.addr = 192.168.3.122; # IP address of the jail
    path = "/zroot/jails/elk"; # Path to the jail
    mount.fstab="/zroot/jails/elk/etc/fstab.java"; # mount local fstab for the java
    }

    cat /zroot/jails/elk/etc/fstab.java
    fdesc /dev/fd fdescfs rw 0 0
    proc /proc procfs rw 0 0

    The rest of the service I ran in jails have no particularities in the defitionions – Apache, wikimedia, Django, OpenVPN

  • Apple TimeMachine config on Debian and FreeBSD

    This is my current working configuration for MacOS Ventura 13.1 for TimeMachine hosted on a RaspberryPi home NAS and FreeBSD server.

    Tested with Samba version 4.13.13-Debian on the RaspberryPi (Conmpute module 4 with IO board), and 4.16.8 on the FreeBSD 13.1.

    The following is added to the smb.conf (in Debian is /etc/samba/smb.conf, in FreeBSD is /usr/local/etc/smb4.conf)

    [TimeMachine]
    path = /nas/backup
    public = yes
    browseable = Yes
    guest ok = yes
    vfs objects = fruit streams_xattr
    read only = No
    inherit acls = Yes
    fruit:time machine = yes
    writeable = yes
    create mask = 0600
    directory mask = 0700
    spotlight = yes
    fruit:nfs_aces = No
    netbios name = freenas
    fruit:aapl = yes
    vfs objects = catia fruit streams_xattr
    fruit:resource = file
    fruit:metadata = stream
    fruit:locking = none
    fruit:encoding = native
    mdns name = mdns
    ea support = yes
    fruit:posix_rename = yes
    fruit:veto_appledouble = no
    fruit:wipe_intentionally_left_blank_rfork = yes
    fruit:delete_empty_adfiles = yes
    fruit:aapl = yes