name: rdp-gateway1 description: LXD profile for lxc devices: disk-device-1: path: /storage pool: btrfs1 source: app type: disk eth0: ipv4.address: 10.1.0.3 network: DMZ security.ipv4_filtering: 'true' security.mac_filtering: 'true' type: nic root: path: / pool: btrfs1 size: 7GiB type: disk config: limits.memory: 2GiB snapshots.schedule: '@daily' snapshots.expiry: 4d cloud-init.network-config: | version: 1 config: - type: physical name: eth0 subnets: - type: static ipv4: true address: 10.1.0.3 netmask: 255.255.255.0 gateway: 10.1.0.1 control: auto user.user-data: | #cloud-config ssh_pwauth: yes package_update: true package_upgrade: true packages: - apache2 - libapache2-mod-security2 - libapache2-mod-qos - podman - fail2ban - tree - ncdu - mariadb-server - aide - cockpit - wireguard-tools - cockpit-pcp - geoip-bin - chrony apt: proxy: http://10.10.10.2:3128 http_proxy: http://10.10.10.2:3128 ftp_proxy: http://10.10.10.2:3128 https_proxy: http://10.10.10.2:3128 runcmd: - hostnamectl set-hostname p-homedmz-guacamole-01 - | #!/bin/bash tee /etc/apache2/sites-available/000-default.conf <<'EOF' ServerAdmin webmaster@localhost ServerName gateway.global-itserv.de DocumentRoot /var/www/html SSLEngine on SSLCertificateFile /root/guacamole/certs/public.crt SSLCertificateKeyFile /root/guacamole/certs/private.key RewriteEngine On RewriteMap ipmap txt:/etc/apache2/blacklist.txt RewriteCond ${ipmap:%{REMOTE_ADDR}} !="" RewriteRule .* - [F,L] ProxyPass http://127.0.0.1:10000/guacamole/ flushpackets=on ProxyPassReverse http://127.0.0.1:10000/guacamole/ ProxyPass ws://127.0.0.1:10000/guacamole/websocket-tunnel ProxyPassReverse ws://127.0.0.1:10000/guacamole/websocket-tunnel ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined EOF rm /etc/apache2/sites-available/default-ssl.conf mkdir -p /root/guacamole/certs cat < /root/guacamole/certs/private.key -----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg1BuIzGAPqLFIdORh ZEtWJJeGM58nWZpeDOs2lOeofVuhRANCAARnAjfHCG+l+PT1Tk/XLwsGaNobDlI8 VKtnwKuzdrbTxNk/RzywT7YjC6edESZHu5KO1jVRJRzxawgv43QgGjsY -----END PRIVATE KEY----- EOF cat < /root/guacamole/certs/public.crt -----BEGIN CERTIFICATE----- MIIDkDCCAxagAwIBAgISAwD3PHREBo72l1DgsiQd3EozMAoGCCqGSM49BAMDMDIx CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF NjAeFw0yNDExMTAxMzE0MDNaFw0yNTAyMDgxMzE0MDJaMCMxITAfBgNVBAMTGGdh dGV3YXkuZ2xvYmFsLWl0c2Vydi5kZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA BGcCN8cIb6X49PVOT9cvCwZo2hsOUjxUq2fAq7N2ttPE2T9HPLBPtiMLp50RJke7 ko7WNVElHPFrCC/jdCAaOxijggIZMIICFTAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0l BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYE FA+VIrtpZCMqSXGhippHELKtyIDsMB8GA1UdIwQYMBaAFJMnRpgDqVFojpjWxEJI 2yO/WJTSMFUGCCsGAQUFBwEBBEkwRzAhBggrBgEFBQcwAYYVaHR0cDovL2U2Lm8u bGVuY3Iub3JnMCIGCCsGAQUFBzAChhZodHRwOi8vZTYuaS5sZW5jci5vcmcvMCMG A1UdEQQcMBqCGGdhdGV3YXkuZ2xvYmFsLWl0c2Vydi5kZTATBgNVHSAEDDAKMAgG BmeBDAECATCCAQMGCisGAQQB1nkCBAIEgfQEgfEA7wB2AOCSs/wMHcjnaDYf3mG5 lk0KUngZinLWcsSwTaVtb1QEAAABkxZrVpYAAAQDAEcwRQIgAOVmfoW9O8dpYRFY DOXoRSQQh7gtq88VbkkxQbQ8aEcCIQCJXncLzYIqB32Je8xLMJXS8XhjXI0S7NVz iz4y9Y+F2QB1AKLjCuRF772tm3447Udnd1PXgluElNcrXhssxLlQpEfnAAABkxZr XZYAAAQDAEYwRAIgB4FisES3mqu+dBjsVkzoEYJJBmTMPfSJ3wJAIkHMlv8CIHgk pjJypKnZj6ieHjWOF8bS3N27XHRu47bwEkmlmgZJMAoGCCqGSM49BAMDA2gAMGUC MQDJEpKHK7zhZ8qG/H+5GDlJluVZ3iGX0ckR/UWHd0YoYas6gQQKidg/YjV7fvrw Y/kCMFrY+9JRLyy5TH4wPHL2TV/61NNlDjLku8xf3ifD4Nh6btApxqE6wHisVzCC eBjRcQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEVzCCAj+gAwIBAgIRALBXPpFzlydw27SHyzpFKzgwDQYJKoZIhvcNAQELBQAw TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg RW5jcnlwdDELMAkGA1UEAxMCRTYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATZ8Z5G h/ghcWCoJuuj+rnq2h25EqfUJtlRFLFhfHWWvyILOR/VvtEKRqotPEoJhC6+QJVV 6RlAN2Z17TJOdwRJ+HB7wxjnzvdxEP6sdNgA1O1tHHMWMxCcOrLqbGL0vbijgfgw gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSTJ0aYA6lRaI6Y1sRCSNsj v1iU0jAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAfYt7SiA1sgWGCIpunk46r4AExIRc MxkKgUhNlrrv1B21hOaXN/5miE+LOTbrcmU/M9yvC6MVY730GNFoL8IhJ8j8vrOL pMY22OP6baS1k9YMrtDTlwJHoGby04ThTUeBDksS9RiuHvicZqBedQdIF65pZuhp eDcGBcLiYasQr/EO5gxxtLyTmgsHSOVSBcFOn9lgv7LECPq9i7mfH3mpxgrRKSxH pOoZ0KXMcB+hHuvlklHntvcI0mMMQ0mhYj6qtMFStkF1RpCG3IPdIwpVCQqu8GV7 s8ubknRzs+3C/Bm19RFOoiPpDkwvyNfvmQ14XkyqqKK5oZ8zhD32kFRQkxa8uZSu h4aTImFxknu39waBxIRXE4jKxlAmQc4QjFZoq1KmQqQg0J/1JF8RlFvJas1VcjLv YlvUB2t6npO6oQjB3l+PNf0DpQH7iUx3Wz5AjQCi6L25FjyE06q6BZ/QlmtYdl/8 ZYao4SRqPEs/6cAiF+Qf5zg2UkaWtDphl1LKMuTNLotvsX99HP69V2faNyegodQ0 LyTApr/vT01YPE46vNsDLgK+4cL6TrzC/a4WcmF5SRJ938zrv/duJHLXQIku5v0+ EwOy59Hdm0PT/Er/84dDV0CSjdR/2XuZM3kpysSKLgD1cKiDA+IRguODCxfO9cyY Ig46v9mFmBvyH04= -----END CERTIFICATE----- EOF tee /etc/apache2/apache2.conf <<'EOF1' DefaultRuntimeDir ${APACHE_RUN_DIR} PidFile ${APACHE_PID_FILE} Timeout 300 KeepAlive On MaxKeepAliveRequests 100 KeepAliveTimeout 5 User ${APACHE_RUN_USER} Group ${APACHE_RUN_GROUP} HostnameLookups Off ErrorLog ${APACHE_LOG_DIR}/error.log LogLevel warn IncludeOptional mods-enabled/*.load IncludeOptional mods-enabled/*.conf Include ports.conf Options FollowSymLinks AllowOverride None Require all denied AllowOverride None Require all granted Options Indexes FollowSymLinks AllowOverride None Require all granted AccessFileName .htaccess Require all denied LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %O" common LogFormat "%{Referer}i -> %U" referer LogFormat "%{User-agent}i" agent IncludeOptional conf-enabled/*.conf IncludeOptional sites-enabled/*.conf RequestReadTimeout header=20-40,MinRate=500 body=20-40,MinRate=500 QS_ClientEntries 100000 QS_SrvMaxConnPerIP 50 MaxClients 250 QS_SrvMaxConnClose 180 QS_SrvMinDataRate 150 1200 SecServerSignature "Zeus/4.3" RemoteIPHeader X-Forwarded-For EOF1 tee /root/blocklist.sh <<'EOF2' #!/bin/bash BLACKLIST_FILE="/etc/apache2/blacklist.txt" echo > "$BLACKLIST_FILE" BANNED_IPS=$(fail2ban-client get guacamole-auth banned) BANNED_IPS=$(echo "$BANNED_IPS" | tr -d "[]',") if [[ -n "$BANNED_IPS" ]]; then echo > "$BLACKLIST_FILE" for ip in $BANNED_IPS; do echo "$ip b" >> "$BLACKLIST_FILE" done fi exit 0 EOF2 tee /etc/fail2ban/jail.d/guacamole-auth.conf <<'EOF3' [guacamole-auth] enabled = true filter = guacamole-auth logpath = /var/log/syslog bantime = 600 findtime = 600 maxretry = 3 action = iptables ignoreip = 127.0.0.1/8 10.0.2.0/24 192.168.0.0/24 EOF3 tee /etc/fail2ban/jail.d/apache.conf <<'EOF31' [apache] enabled = true filter = apache logpath = /var/log/apache2/access.log bantime = 600 findtime = 600 maxretry = 3 action = iptables ignoreip = 127.0.0.1/8 10.0.2.0/24 192.168.0.0/24 EOF31 tee /etc/fail2ban/filter.d/guacamole-auth.conf <<'EOF4' [Definition] failregex = .*Authentication attempt from \[,.*\].*failed.* ignoreregex = EOF4 tee /etc/fail2ban/filter.d/apache.conf <<'EOF41' [Definition] failregex = .*HTTP\/1.1\" 404 .* ignoreregex = EOF41 - sed -i '/^actionban =.*iptables/s/$/\n \/root\/blocklist.sh /' /etc/fail2ban/action.d/iptables.conf - sed -i '/^actionunban =.*iptables/s/$/\n \/root\/blocklist.sh /' /etc/fail2ban/action.d/iptables.conf - chmod +x /root/blocklist.sh - cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local - a2enmod rewrite proxy proxy_http proxy_wstunnel headers reqtimeout remoteip ssl - touch /etc/apache2/blacklist.txt - systemctl restart apache2 - echo '' | tee /var/www/html/index.html > /dev/null - sed -i 's/^ServerTokens .*/ServerTokens OS/' /etc/apache2/conf-available/security.conf - sed -i 's/^ServerSignature .*/ServerSignature On/' /etc/apache2/conf-available/security.conf - systemctl restart apache2 - fail2ban-client reload - sed -i 's/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/' /etc/mysql/mariadb.conf.d/50-server.cnf - sed -i 's/^#\?key_buffer_size\s*=.*/key_buffer_size = 16M/' /etc/mysql/mariadb.conf.d/50-server.cnf - sed -i 's/^#\?max_allowed_packet\s*=.*/max_allowed_packet = 32M/' /etc/mysql/mariadb.conf.d/50-server.cnf - sed -i 's/^#\?thread_stack\s*=.*/thread_stack = 256K/' /etc/mysql/mariadb.conf.d/50-server.cnf - sed -i 's/^#\?thread_cache_size\s*=.*/thread_cache_size = 8/' /etc/mysql/mariadb.conf.d/50-server.cnf - sed -i 's/^#\?max_connections\s*=.*/max_connections = 20/' /etc/mysql/mariadb.conf.d/50-server.cnf - sed -i 's/^#\?table_cache\s*=.*/table_cache = 64/' /etc/mysql/mariadb.conf.d/50-server.cnf - echo "CREATE DATABASE guacamole;" | sudo mysql -u root - echo "GRANT ALL PRIVILEGES ON guacamole.* TO 'guacamole_user1'@'%' IDENTIFIED BY 'PASSWORD3'; FLUSH PRIVILEGES;" | sudo mysql -u root - systemctl restart mariadb - mkdir -p /root/guacamole/ca - | #!/bin/bash tee /root/guacamole.sh <<'EOF5' #!/bin/bash export http_proxy=http://10.10.10.2:3128 export https_proxy=http://10.10.10.2:3128 export ftp_proxy=http://10.10.10.2:3128 export no_proxy=localhost,127.0.0.1 podman pull docker.io/guacamole/guacd:1.5.5 podman pull docker.io/guacamole/guacamole:1.5.5 EOF5 - mkdir -p /usr/lib/check_mk_agent/local - | #!/bin/bash tee /usr/lib/check_mk_agent/local/podman_status.sh <<'EOF6' #!/bin/bash running_containers=$(podman ps --format "{{.Names}}" | wc -l) total_containers=$(podman ps -a --format "{{.Names}}" | wc -l) container_names=$(podman ps --format "{{.Names}}" | tr '\n' ',' | sed 's/,$//') if [ "$running_containers" -lt "$total_containers" ]; then echo "2 podman_running - Only $running_containers/$total_containers Podman containers are running: $container_names" else echo "0 podman_running - $running_containers/$total_containers Podman containers are running: $container_names" fi EOF6 tee /usr/lib/check_mk_agent/local/403_status.sh <<'EOF61' #!/bin/bash #!/bin/bash LOGFILE="/var/log/apache2/access.log" output=$(cat "$LOGFILE" | awk -v date="$(date --date='5 minutes ago' '+%d/%b/%Y:%H:%M:%S')" '$4 > "["date && $9 == 403 {count[$1]++} END {for (ip in count) print ip, count[ip]}') status=0 message="" temp_message="" if [[ -n "$output" ]]; then while read -r ip count; do if [[ -n "$ip" && -n "$count" ]]; then temp_message+=" $ip($count)" if [[ "$count" -gt 10 ]]; then status=2 elif [[ "$count" -gt 0 && "$status" -ne 2 ]]; then status=1 fi fi done <<< "$output" if [[ -n "$temp_message" ]]; then message="$temp_message" else message="keine 403 Aufrufe" fi else message="keine 403 Aufrufe" fi echo "$status \"Apache 403 Check\" - $message" EOF61 - chmod +x /usr/lib/check_mk_agent/local/podman_status.sh - chmod +x /usr/lib/check_mk_agent/local/403_status.sh - chmod +x /root/guacamole.sh - /root/./guacamole.sh - podman run -d --no-healthcheck --name guacd -p 4822:4822 docker.io/guacamole/guacd:1.5.5 - podman run -d --no-healthcheck --name guacamole -p 10000:8080 -e JAVA_OPTS="-Xms256m -Xmx256m" --memory=512m -e GUACD_LOG_LEVEL=trace -e GUACD_HOSTNAME=10.0.1.2 -e GUACD_PORT=4822 -e MYSQL_HOSTNAME=10.0.1.2 -e MYSQL_DATABASE=guacamole -e MYSQL_USER=guacamole_user1 -e MYSQL_PASSWORD="PASSWORD3" -e LDAP_HOSTNAME=10.0.2.2 -e LDAP_PORT=389 -e LDAP_USER_BASE_DN="DC=domain,DC=ads" -e LDAP_SEARCH_BIND_DN="uid=service_guacamole,cn=users,cn=accounts,dc=domain,dc=ads" -e LDAP_SEARCH_BIND_PASSWORD="PASSWORD3" -e LDAP_USER_ATTRIBUTES=uid -e LDAP_USER_SEARCH_FILTER="(memberOf=cn=guacamole_user,cn=groups,cn=accounts,dc=domain,dc=ads)" -e TOTP_ENABLED=true -e TOTP_ISSUER=domain.ads docker.io/guacamole/guacamole:1.5.5 - #LDAP_PORT=636 -e LDAP_ENCRYPTION_METHOD=ssl - timedatectl set-timezone Europe/Berlin - systemctl daemon-reload - systemctl enable --now chrony - chronyc sources - sed -i '/^server /d' /etc/chrony/chrony.conf - echo "server 10.0.2.2 iburst" >> /etc/chrony/chrony.conf - systemctl restart chronyd - cd /etc/systemd/system/ - podman generate systemd --name guacd --files - podman generate systemd --name guacamole --files - systemctl daemon-reload - systemctl enable container-guacd - systemctl enable container-guacamole - systemctl start container-guacd container-guacamole - mkdir -p /etc/systemd/system/fwupd-refresh.service.d - | #!/bin/bash tee /etc/systemd/system/fwupd-refresh.service.d/proxy.conf <<'EOFproxy' [Service] Environment="https_proxy=http://10.10.10.2:3128" EOFproxy - systemctl daemon-reload - systemctl reset-failed - sed -i 's/^#CRON_DAILY_RUN=yes/CRON_DAILY_RUN=yes/' /etc/default/aide - sed -i 's/^Checksums = .*/Checksums = sha256/' /etc/aide/aide.conf - aideinit - mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db - service cron restart - mkdir -p /var/spool/cron/crontabs/ - touch /var/spool/cron/crontabs/root - | #!/bin/bash tee /root/aide.sh <<'EOF7' #!/bin/bash /usr/bin/aide -check -c /etc/aide/aide.conf|tee /tmp/aide_report.log rm /var/lib/aide/aide.db /usr/bin/aide --init -c /etc/aide/aide.conf mv /var/lib/aide/aide.db.new /var/lib/aide/aide.db EOF7 tee /usr/lib/check_mk_agent/local/10_aide_summary <<'EOF8' #!/bin/bash touch /tmp/aide_report.log SUMMARY=$(cat /tmp/aide_report.log | grep -A 5 "Summary:") ADDED=$(echo "$SUMMARY" | grep "Added entries:" | awk '{print $3}') REMOVED=$(echo "$SUMMARY" | grep "Removed entries:" | awk '{print $3}') CHANGED=$(echo "$SUMMARY" | grep "Changed entries:" | awk '{print $3}') if [[ "$CHANGED" -eq 0 && "$ADDED" -eq 0 && "$REMOVED" -eq 0 ]]; then STATUS=0 # OK (grĂ¼n) MESSAGE="No changes, additions, or removals detected" else STATUS=2 # CRITICAL (rot) MESSAGE="Changes detected: $CHANGED changes, $ADDED added, $REMOVED removed" fi echo "$STATUS aide_summary - $MESSAGE" EOF8 tee /etc/aide/aide.conf.d/exclude <<'EOF9' !/run/containers/storage/overlay-containers/ !/var/lib/containers/ !/tmp/report.log !/run/systemd/propagate/systemd-timedated.service !/var/lib/check_mk_agent/rtc_remotes/ !/var/log/sysstat/ !/var/lib/aide/aide.db !/tmp/aide_report.log EOF9 - chmod +x /usr/lib/check_mk_agent/local/10_aide_summary - chmod +x /root/aide.sh - echo "0 */1 * * * root /root/aide.sh" > /var/spool/cron/crontabs/root - echo "0 0 * * * podman exec guacamole rm -rf /etc/guacamole/session/*" >> /var/spool/cron/crontabs/root - systemctl stop ufw - systemctl disable ufw - echo "proc /proc proc defaults,hidepid=2 0 0" >> /etc/fstab - systemctl daemon-reload - mount -o remount /proc - rm -rf /var/lib/cloud/* - systemctl disable cloud-init - systemctl stop cloud-init access_entitlements: - can_delete - can_edit project: default