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