Posts filed under Security

Raspberry Pi OPNsense Captive Portal Voucher Generation

When I received my new HP/Aruba iAP-305-RW access points I started to think about introducing a wireless guest network. Not a network with a pre-shared key, but something more secure and flexible. The HP/Aruba AP’s have the option for captive portal, but it doesn’t have a good integration with ACME/Let’s Encrypt certificates. My OPNsense firewall has very good integration with ACME/Let’s Encypt, and has the option of deploying a Captive Portal.

Configuring the Captive Portal on the OPNsense firewall is pretty straightforward. It’s well documented, and is up-and-running in minutes. The main challenge was creating a way to supply the credentials to the users. The default option is to generate voucher codes and print them. Not really an option, since I loose those pieces of paper before I even printed them.

The newer OPNsense software has a decent API, which also includes API options for captive portal. This opened up an option including a Raspberry Pi.

Posted on July 19, 2023 and filed under Programming, Raspberry Pi, Security, Gadgets.

My First Docker Deployment

About two weeks ago I had to get a crash-course in Docker technology at work. I had no idea what I was doing (following a YouTube video and an accompanying PDF. Eventually I got it to work but no idea what I was doing. So I wanted to change that.

NOTE: I’m not gonna build/create new docker containers yet. Just learning on how they are used, configured, and interact. This is also no tutorial on how to install Docker itself. There are more than enough websites for that.

The problem with learning new things is that they have to be practically and/or useful (for me). After some thought I ended up with a combination of Transmission and OpenVPN.

This Docker image gives you a Torrent client with a webgui, and all (torrent) traffic is directed through the OpenVPN connection. Making it safe to download Linux distro’s. As a bonus, it has a generic web proxy function with you can use to handle your web traffic. The latter is especially useful in combination with e.g. the browser extension/plugin FoxyProxy.

Deploying the docker container is pretty straight-forward (you do need a supported VPN provider). It basically works out of the box, but molding it to my wishes involved a bit more digging around. There are some things I wanted to add, or change;

  • Customer paths for the download locations (default = /data).

  • Use a watchfolder for transmission where the .torrent files can be picked-up.

  • Use an additional reverse proxy for the Transmission webGui so that all my internal services are accessible from 1 IP address without having to remember al their TCP ports.
    More info on that can be found here.

  • Since the Docker container runs under a/the root account, I needed to change that behavior since I don’t want to do everything with root permissions (involving experimentation with umask and UID/GID’s).

This resulted in the following docker-compose file (docker-compose.yaml):

UPDATE: I’ve added the Portainer image to the compose file. This gives you a web gui to manage the containers. The gui is accessible on port 9000 on the same docker host.

version: '2'
services:
    transmission-openvpn:
        restart: unless-stopped
        volumes:
            - '/mnt/data:/data'
            - '/mnt/stack/Watchfolder:/home/Watchfolder'
            - '/etc/localtime:/etc/localtime:ro'
        environment:
            - TZ=Europe/Amsterdam
            - OPENVPN_OPTS=--inactive 3600 --ping 10 --ping-exit 60
            - CREATE_TUN_DEVICE=true
            - OPENVPN_PROVIDER=NORDVPN 
            - OPENVPN_USERNAME=<VPN-USERNAME>
            - OPENVPN_PASSWORD=<VPN-PASSWORD>
            - NORDVPN_COUNTRY=CH
            - HEALTH_CHECK_HOST=google.com
            - TRANSMISSION_INCOMPLETE_DIR_ENABLED=true
            - TRANSMISSION_INCOMPLETE_DIR=/data/downloads/incomplete
            - TRANSMISSION_DOWNLOAD_DIR_ENABLED=true
            - TRANSMISSION_DOWNLOAD_DIR=/data/downloads/complete
            - TRANSMISSION_WATCH_DIR_ENABLED=true
            - TRANSMISSION_WATCH_DIR=/home/Watchfolder
            - TRANSMISSION_TRASH_ORIGINAL_TORRENT_FILES=true
#            - TRANSMISSION_UMASK=222
            - TRANSMISSION_SPEED_LIMIT_DOWN=5000
            - TRANSMISSION_SPEED_LIMIT_DOWN_ENABLED=true
            - TRANSMISSION_SPEED_LIMIT_UP=1000
            - TRANSMISSION_SPEED_LIMIT_UP_ENABLED=true
            - WEBPROXY_ENABLED=true
            - WEBPROXY_PORT=8080
            - LOCAL_NETWORK=192.168.0.0/16
            - PUID=1000
            - PGID=1000
        cap_add:
            - NET_ADMIN
        logging:
            driver: json-file
            options:
                max-size: 10m
        ports:
                - '9091:9091'
                - '8888:8080'
        image: haugene/transmission-openvpn
        container_name: openvpn
    portainer:
        image: portainer/portainer-ce
        container_name: portainer
        restart: always
        ports:
          - "9000:9000"
        command: -H unix:///var/run/docker.sock
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
          - portainer_data:/data

volumes:
  portainer_data:

The thing that took the most amount of time to figure out was the PUID/PGID part of the config. This basically are the user id and group id which are used to run the container and also when creating directories and files on the physical filesystem of the host. In my case, the PUID, and PGID are the id’s corresponding to my username on the Linux host.

The important part is that all the path references in the environment part of the yaml file are local to the container. These are mapped/related to the physical locations in the volumes part of the config file.

Deploying/creating the Docker container is done through the following command (I use docker-compose instead of docker run):

docker-compose up -d

Configuring a webproxy in my browser pointing to the Linux host IP with port 8888 allows me to surf the web through the OpenVPN provider. Pointing my browser to the Linux host IP address with port 9091 gives the Transmission webGui (http://IP-ADDRESS>:9091). But as I mentioned earlier, I want to access this through my internal reverse proxy (NGINX).

To do this I have to create an additional location within the NGINX config and enable that. This resulted in the following NGINX location config file:

location /transmission/ {
      proxy_pass http://192.168.##.1:9091;

      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-NginX-Proxy true;
      proxy_http_version 1.1;
      proxy_set_header Connection "";
      proxy_pass_header X-Transmission-Session-Id;
      add_header   Front-End-Https   on;

      satisfy any;
      allow 192.168.0.0/16;
      allow 172.16.16.0/24;
      allow 10.200.200.200/32;
      deny all;
      auth_basic "Restricted Content";
      auth_basic_user_file /etc/nginx/auth.d/auth.pwd;
}

Note that the bottom part are some directoves to limit the IP’s that can access the page. These are related to your internal IP networks.

Now I can access the tranmission webGui over https through my NGINX reverse proxy via https://internalhost/transmission

A small note on the use of FoxyProxy; This extension allows you to selectively use the proxy based on (parts of ) URL. You can configure patterns using wildcards and regular expressions to direct traffic directly or through a proxy.

So if e.g. your OpenVPN terminates in the the US, you can create a pattern that certain entertainment sites are being accessed through your proxy, while other traffic uses your regular ISP. This is especially useful if you have a capped monthly VPN account.

Posted on July 29, 2020 and filed under Linux, Programming, Security, Software, Tips'n Tricks.

Keepass Password Generator

With the increasing password complexity demands in both online and offline services, you basically can’t live without a password manager. Personally I use 1Password, but at work Keepass is recommended. Main reason is that it remains local (no passwords in the cloud). Downside is that you need to have a proper backup in case of emergencies (or rely on decent password reset mechanisms.

Since a generic password scheme is obvious highly overrated, you basicalle need a different password scheme for every website, application or service. The worst being password schemes that limit the amount of characters to between 6 and 10…. Seriously? Others limit the amount of special characters like @\/’”| because of some fear of SQL injection schemes. Which is not a problem if you implement the backend correctly…. But that’s for another day.

Due to all these password challenges I had to reconfigure my Keepass (default) password generator to be a bit more friendly. For those bad password scheme website I have specific generation algoritms, and in a few cases the demands on the password are so ridiculous that I had to make a generator just for that service.

Anyway, the latest ‘challenge’ was that a service demanded a letter at the start and finish of the password, so that resulted in the following pattern:

L[uullddss]{22}L

keepass_pswd_gen_01.png

This results in a password:

  • Starting with a mixed-case letter (L), followed by a 22 character mix of at least

  • 2 upper-case (uu) letters (ABCDEFGHIJKLMNOPQRSTUVWXYZ),

  • 2 lower-case (ll) letters (abcdefghijklmnopqrstuvwxyz),

  • 2 digits (dd) (1234567890),

  • 2 printable special characters (ss) ( !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ ),

  • and finishing with another mixed case letter (ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)

Note that the previous default password length was 22 character, so increasing it with 2 additional letters to 24, the password became a bit stronger. Otherwise the password would have weakened substantially, because the first and last character was one out of 52.

This results in the following preview:

When you need to communicate passwords, or manual type them (on another device) it might be helpful to exclude certain characters that (depending on the font) look alike (e.g. 1Il|, O0). This can be accomplished in the ‘Advanced’ tab of the password generator.

Note that excluding these characters reduce the complexity of the password (which can be corrected up to some extend by increasing the password length).

And in those weird cases where certain character are not allowed you can use the ‘exclude characters’ option in the screenshot above (make sure you increase the password length accordingly to maintain password security).

Posted on June 8, 2020 and filed under Security, Tips'n Tricks.

Xiaomi Xiaofang Wireless Camera Custom Firmware Hack

A colleague of mine demonstrated a Wyze webcam a couple of weeks before. A nifty little FullHD wireless IP camera that has a decent (iOS/Android) app and cloud connectivity to store the data.
I liked everything about it, except the cloud-storage part. I don’t like it when I don’t know where my private data resides. So I started a to search to see if these devices could be altered to benefit my needs, and guess what, they can be altered.

There’s a github project where they fabricated a firmware hack and with custom software the camera can be used for much more. So now I had to get my hands on the most inexpensive version of the camera. Since there are different brands that ship basically the same hardware with a different firmware, there’s more than enough choice.

Posted on November 19, 2019 and filed under Gadgets, Hardware, Security, Review, Tips'n Tricks.

Cisco ISE MAC Addresss Database Clean Up

Imagine having 15.000+ MAC addresses in a Cisco ISE database. All these MAC addresses are used to gain access to wireless networks protected with WPA2-PSK and MAC-filtering. But how to make sure that they are all (still) valid?

Remove MAC Addresses After Change In Authentication

Finally, the time has come to implement 802.1x on the wireless network for a substantial amount of these devices. These devices are consist mainly of Windows machines or Thin Clients. Both of those are managed through either the Microsoft Active Directory or a Thin Client Management Suite. So, applying setting related to 802.1x are pretty straight forward to distribute. There are however some Windows / Thin client devices that will remain on the MAC-filtering wifi networks for numerous reasons.

After a few tests the migration of the new 802.1x devices has started, but is leaving us with a MAC Address database filled with addresses that can be removed, since they are no longer used…. But how to do that? Cisco ISE has a lot of features, and is capable of generating rich reports about almost everything. However it has no way of reporting on dot1x devices that might still remain in the MAC address database as well. That is where I had to become creative.

First I explored the Cisco ISE Monitoring API, but that only gives active connections. There’s no way of exploring past (successful) authentications/authorizations. I needed a way to get current and past successful dot1x authentications and compare the MAC addresses associated with those entries to the MAC address database, and remove those from that database.

Eventually, I found two paths to accomplish this; First through the reporting module. There you can export all RADIUS authentications to CSV. Filtering these results in Excel, or through Python scripting, you are able to extract the MAC Addresses that successfully authenticated with dot1x. Feed these MAC addresses to a script and remove them through the Cisco ISE ERS API. Or if you’ve got nothing else to do; do it by hand.

The other path is by following the syslog output and parsing that feed. The downside to this is that you have to have syslog file access or add an additional syslog server to Cisco ISE that you may access (e.g. your scripting machine). The syslog version makes a a bit more tricky, since the (syslog)log lines are very long and you have to combine the correct lines to get the full message. Parsing CSV is much easier, so I followed that path first.

Dormant/Obsolete MAC Addresses

Another issue with static MAC addresses (and even local accounts) is that they tend to remain indefinitely in the MAC database. Lang after devices have been decommissioned, the MAC address remains. Which leaves a security hole to be exploited.

By using the generated ‘RADIUS Authentications’ reports over a longer time (e.g. 90 days) you can do a cross reference with MAC addresses in the database and recent successful authentications of that MAC address.
There are some caveats though;

  1. you need a session-timeout on the network (either statically defined on the network device) or by RADIUS return attribute, so that devices have to re-authenticate periodically. Otherwise you might not see a valid device in the logging and removed it by mistake.

  2. RADIUS Reporting goes only 30 days back, so you have to combine several (scheduled) reports to achieve a longer time span. There used to be a custom time frame option, but seems to have disappeared in version 2.6

Cisco ISE v2.6 and Google ChromeOS

While playing around with the new Cisco Identity Service Engine (ISE) v2.6 (patch2) I stumbled upon a security feature while testing Wireless 802.1x access with an Acer Chromebook (ChromeOS v75.0.3770.144). When connecting to the 802.1x enabled SSID the connection failed, while other devices (Windows 10, Apple iOS and MacOS) connected just fine.

The problem is the client EAP handshake and usually this relates to untrusted server certificates. This happens to me a lot since I use different RADIUS services for my testing SSID’s.
So after clearing the SSID settings (forget) on the Chromebook it should work, but it didn’t.

The logging showed that the EAP handshake failed because the client didn’t offer a suitable cipher to the ISE server.

Turns out that Cisco ISE v2.6 has SHA1 disabled by default, and you need to enable it in:

Administration -> System -> Settings -> Security Settings

With the setting ‘Allow SHA1 Ciphers’, and ‘Allow only TLS_RSA_WITH_AES_128_CBC_SHA’ the Chromebook was able to connect to the 802.1x enabled SSID using old/depricated ciphers.

Now I wonder why the Chromebook still uses SHA1 based ciphers for secure communications, since Google Chrome started to abandon SHA1 as one of the first browsers….

Even installing the ‘Powerwash for added security’ feature in ChromeOS didn’t enable or add stronger ciphers on the Chromebook.

Posted on July 31, 2019 and filed under Tips'n Tricks, Security.

Juniper SRX, Virtual Routers, and SNMPv3

In this continuing story about Junos and virtual routers an episode about SNMPv3.

A simple SNMPv3 config for Junos would be the following:

set snmp v3 usm local-engine user authpriv authentication-md5 authentication-password My_Password_01
set snmp v3 usm local-engine user authpriv privacy-aes128 privacy-password My_Password_02
set snmp v3 vacm security-to-group security-model usm security-name v3test group v3test
set snmp v3 vacm security-to-group security-model usm security-name authpriv group v3test
set snmp v3 vacm access group v3test default-context-prefix security-model any security-level authentication read-view v3testview
set snmp v3 vacm access group v3test default-context-prefix security-model any security-level authentication write-view v3testview
set snmp v3 vacm access group v3test default-context-prefix security-model any security-level authentication notify-view v3testview
set snmp v3 vacm access group v3test default-context-prefix security-model any security-level privacy read-view v3testview
set snmp v3 vacm access group v3test default-context-prefix security-model any security-level privacy write-view v3testview
set snmp v3 vacm access group v3test default-context-prefix security-model any security-level privacy notify-view v3testview
set snmp v3 snmp-community v3test security-name v3test
set snmp view v3testview oid system include
set snmp view v3testview oid .1 include

Authenticating with the correct credentials (U: authpriv, P: My_Password_01) will give results in a single (default) virtual router.

Using this config in a multiple VR environment will result in Authentication and/or authorization errors. Reason being the not using the root/single VR configuration.

Adding some details to the config, AND altering the actual SNMPv3 query will solve that.

set snmp v3 usm local-engine user authpriv authentication-md5 authentication-password My_Password_01
set snmp v3 usm local-engine user authpriv privacy-aes128 privacy-password My_Password_02
set snmp v3 vacm security-to-group security-model usm security-name authpriv group v3test
set snmp v3 vacm access group v3test context-prefix DEFAULT security-model any security-level authentication read-view v3testview
set snmp v3 vacm access group v3test context-prefix DEFAULT security-model any security-level authentication write-view v3testview
set snmp v3 vacm access group v3test context-prefix DEFAULT security-model any security-level authentication notify-view v3testview
set snmp v3 vacm access group v3test context-prefix DEFAULT security-model any security-level privacy read-view v3testview
set snmp v3 vacm access group v3test context-prefix DEFAULT security-model any security-level privacy write-view v3testview
set snmp v3 vacm access group v3test context-prefix DEFAULT security-model any security-level privacy notify-view v3testview
set snmp v3 snmp-community v3test security-name v3test
set snmp view v3testview oid system include
set snmp view v3testview oid .1 include
set snmp routing-instance-access access-list DEFAULT

The main differences are:

  • context-prefix <VR-NAME>
  • snmp routing-instant-access access-list <VR-NAME>

Having done that, AND adding a context parameter to the actual query will give the correct results.

Posted on June 27, 2018 and filed under Junos, Security, Tips'n Tricks.

Juniper SRX, Routing Instances, and Syslog Challenges

In the previous post I described the issue I had with routing instances and DHCP-relay, and how I fixed it. It turns out that DHCP-relay wasn't my only problem. Turns out that syslog also stopped at the time I implemented the routing instances.

Syslog-gap

To solve this I needed to inject the route to my syslog server (Splunk) in the global routing instance by using policy options.

set policy-options policy-statement syslog-policy term 10 from instance DEFAULT
set policy-options policy-statement syslog-policy term 10 from route-filter 192.168.20.0/24 exact
set policy-options policy-statement syslog-policy term 10 then accept
set policy-options policy-statement syslog-policy then reject

set routing-options instance-import syslog-policy
Posted on June 25, 2018 and filed under Annoying, Security, Tips'n Tricks.

Juniper SRX, Virtual Routers and DHCP Relay

A couple of weeks ago, I started to implement virtual routers in my SRX300. The reason being a new external subnet that  needed to route to a specific security zone. Using the default VR only wouldn't work because of the (single) default route.

Implementing it was fairly easy. The trouble began this week;

  • Wireless controller not accessible
  • Client with weird behaviour
  • etc.

In my network, I have 1 DHCP server serving multiple internal subnets. The (basic) DHCP relay configuration was:

set forwarding-options dhcp-relay maximum-hop-count 10
set forwarding-options dhcp-relay client-response-ttl 10
set forwarding-options dhcp-relay server-group DHCP_Server 192.168.x.x
set forwarding-options dhcp-relay active-server-group DHCP_Server
set forwarding-options dhcp-relay group clients active-server-group DHCP_Server
set forwarding-options dhcp-relay group clients interface ge-0/0/0.1
set forwarding-options dhcp-relay group clients interface ge-0/0/0.20
set forwarding-options dhcp-relay group clients interface ge-0/0/0.30
set forwarding-options dhcp-relay group clients interface ge-0/0/0.200

Turns out that this stops to function when implementing Virtual Routers. Something I forgot to adjust. And since the DHCP scope on my server was set to a lease-time of 14 days.... That means that problems tend to introduce themselves after a couple of days.....

Anyway, after changing the DHCP relay configuration to include the correct Virtual Router name (DEFAULT) everything worked just fine.

set routing-instances DEFAULT forwarding-options dhcp-relay maximum-hop-count 10
set routing-instances DEFAULT forwarding-options dhcp-relay client-response-ttl 10
set routing-instances DEFAULT forwarding-options dhcp-relay server-group DHCP_Server 192.168.x.x
set routing-instances DEFAULT forwarding-options dhcp-relay active-server-group DHCP_Server
set routing-instances DEFAULT forwarding-options dhcp-relay group clients active-server-group DHCP_Server
set routing-instances DEFAULT forwarding-options dhcp-relay group clients interface ge-0/0/0.1
set routing-instances DEFAULT forwarding-options dhcp-relay group clients interface ge-0/0/0.20
set routing-instances DEFAULT forwarding-options dhcp-relay group clients interface ge-0/0/0.30
set routing-instances DEFAULT forwarding-options dhcp-relay group clients interface ge-0/0/0.200

So. DHCP is a bit like DNS. Both have timers (TTL and lease-time) that might bite you in the butt.

Posted on June 10, 2018 and filed under Annoying, Junos, Security.

Juniper vSRX Firewall and VMWare Workstation 14

For a work related project, I wanted to run the Juniper vSRX firewall (v15.1X49-D110) on my work laptop by using VMWare Workstation Pro 14. Unfortunately, the installation (importing the Juniper vSRX OVA file resulted in a VMWare Workstation crash.