Nach Upgrade auf 7.3 an Schulkonsole keine Anmeldung mehr möglich

Hallo zusammen,

das Upgrade von 7.2 auf 7.3 war zwar erfolgreich, allerdings ist nun keine Anmeldung mehr an der Schulkonsole möglich, außer mit dem Benutzer root.

Installierte Versionen der linuxmuster.net-Pakete:

Beim Anmeldevorgang erscheint folgende Fehlermeldung.

Ldap server down: {'result': -1, 'desc': "Can't contact LDAP server", 'errno': 13, 'ctrls': [], 'info': 'Permission denied'}

Die gesamte Fehlermeldung habe ich leider nur als Screenshot. Komme gerade nicht anders ran…

Folgende Tests/Analysen habe ich durchgeführt:

  1. Die Datei /etc/linuxmuster/.secret/administrator ist vorhanden und hat die Rechte:

    -r-------- 1 root root 16 Jul 10  2020 /etc/linuxmuster/.secret/administrator
    
  2. Den Samba-AD-DC Service habe ich mehrfach neu gestartet. Status zeigt

    Active: active (running)
    
  3. LDAP ist auf Port 636 erreichbar und das Zertifikat ist OK.

  4. Die Datei /etc/linuxmuster/webui/config.yml sieht für mich vollständig aus.
    grafik

  5. Login an den Clients mit Lehrer- und Schüler-Accounts funktioniert.
    Allerdings erscheint im Browser immer der Dialog für die Proxy-Authentifizierung.

  6. Ein ldapsearch auf dem Server liefert mit

    ldapsearch -x -H ldaps://localhost:636 -LLL "sAMAccountName=global-admin" -b 'DC=DOMAINNAME,DC=TLD' -D 'CN=Administrator,CN=Users,DC=DOMAINNAME,DC=TLD' -w $(cat /etc/linuxmuster/.secret/administrator) cn
    

    und mit

    ldapsearch -x -H ldap://localhost:389 -LLL "sAMAccountName=global-admin" -b 'DC=DOMAINNAME,DC=TLD' -D 'CN=Administrator,CN=Users,DC=DOMAINNAME,DC=TLD' -w $(cat /etc/linuxmuster/.secret/administrator) cn
    

    beides Mal folgende Ausgabe.

  7. Die Datei /etc/ldap/ldap.conf hat folgenden Inhalt:


    Ein TLS_REQCERT never brachte auch nicht den gewünschten Erfolg.

  8. Die /etc/samba/smb.confhat folgenden Inhalt:

Ich bin gerade mit meinem Latein ziemlich am Ende. Hast Du @Arnaud aus Entwicklersicht noch eine Idee?

Vielen Dank fürs Mitdenken.

Viele Grüße
Jürgen

Hi Jürgen,

Wie würde die Webui gestartet ? Als root oder mit sudo ?

Was ergibt das folgende in einem Python-Konsole (als root ausgeführt ?)

from linuxmusterTools.ldapconnector import LMNLdapReader as lr
lr.get('/users/USER') # USER durch echte Login ersetzen

Ich bin ein bisschen AFK dieses Wochenende, aber wir werden schon eine Lösung finden :wink:

Gruß

Arnaud

Hallo Arnaud,

Danke für die schnelle Antwort.

Die WebUI wurde als root gestartet.

Hier die gewünschte Ausgabe (leider auch nur als Screenshot :confused:)

Viele Grüße
Jürgen

Hallo Jürgen,

läuft den der AD Dienst?

service samba-ad-dc status

LG
Holger

Hallo Holger,

ja, der läuft (siehe auch Eingangspost Punkt 2).

LG
Jürgen

Halo Jürgen,

Ok, danke, LMNTools hat kein Problem die Daten zu holen, das ist schon mal sehr gut. Klappt der ldapsearch mit den Credentials von global-binduser ?

Gruß

Arnaud

Hallo Arnaud,

ja das scheint zu funktionieren. ldapsearch als root liefert mit der Abfrage

ldapsearch -x -H ldaps://localhost:636 -LLL "sAMAccountName=global-binduser" -b 'DC=DOMAINNAME,DC=TLD' -D 'CN=global-binduser,OU=Management,OU=Global,DC=DOMAINNAME,DC=TLD' -w $(cat /etc/linuxmuster/.secret/global-binduser) cn

folgenden Output

ldapsearch auf Port 389 funktioniert ebenfalls.

Viele Grüße
Jürgen

Hallo @Arnaud,

was mir beim weiteren Testen aufgefallen ist: Selbst wenn ich in der WebUI falsche Credentials eingebe, dann kommt nicht etwa die erwartete Exception Invalid credentials, sondern ebenfalls Ldap server down.
Es scheint, als ob die WebUI den LDAP überhaupt nicht erreichen kann. Liegt das vielleicht daran, dass wir als Hostname für den Server nicht server sondern einen anderen Namen verwendet haben?

Das könnte auch erklären, warum die Abfrage mittels linuxmusterTools.ldapconnector direkt auf dem Server erfolgreich ist, mit der WebUI nicht.
Wenn ich den Programmcode in

/usr/lib/python3/dist-packages/linuxmusterTools/ldapconnector/connector.py

richtig interpretiere, dann wird dort eine Unterscheidung getroffen zwischen „direkt auf dem Server ausgeführt“ und „von der WebUI importiert“.

Viele Grüße
Jürgen

Hallo @juergen,

Ja, genau, es gibt genau dieser Unterschied. Aber beim egal ob direkt oder mit dem import, die angefragte URL bleibt die gleiche: ldaps://localhost:636. Also, das Problem liegt nicht am Servername.

Was mich hier wundert ist die Meldung „Permission denied“, das passt nicht so ganz mit Ldap Down. Gibt es evtl eine andere Fehlermeldung in /var/log/ajenti/ajenti.log ?

So dass du es testen kann, habe ich folgender Skript vorbereitet:

import ldap
from linuxmusterTools.lmnfile import LMNFile

config_path = '/etc/linuxmuster/webui/config.yml'

with LMNFile(config_path, 'r') as webui:
    config = webui.read()
    params = config['linuxmuster']['ldap']

binddn = params['binddn']
bindpwd = params['bindpw']

# ALTERNATIVE zum testen
# binddn = "CN=global-binduser,OU=Management,OU=Global,DC=DOMAINNAME,DC=TLD"
# bindpw = "MY_STRONG_PASSWORD"

conn = ldap.initialize("ldaps://localhost:636/")

# Optionen
conn.set_option(ldap.OPT_REFERRALS, 0)
conn.set_option(ldap.OPT_RESTART, ldap.OPT_ON)
conn.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_ALLOW)
conn.protocol_version = ldap.VERSION3

conn.bind_s(binddn, bindpwd)

conn.unbind()

(als testscript.py z.B. speichern).

Das kann man einfach mit python3 testscript.py als root ausführen. Das macht nichts anderes als eine Verbindung mit LDAP mit den Webui Credentials aufzubauen, mit den gleichen Optionen wie im LMNTools. Es wird auch keinen Output geben, das Ziel ist eine bessere Fehlermeldung zu erhalten.
Das kannst du in Ruhe testen, und auch z.B. binddn und bindpw mit anderen Credentials ersetzen, und evtl die 4 Optionen auskommentieren, vielleicht liegt es auch daran.

Hoffentlich kann man damit das Problem eingrenzen.

Gruß

Arnaud

Hallo Arnaud,

vielen lieben Dank für Deinen unermüdlichen Einsatz und danke für das Testskript. Zu den Ergebnissen der Ausführung von testscript.py siehe unten.

Hier zunächst ein Auszug des Logfiles /var/log/ajenti/ajenti.log. Darin enthalten ist der Neustart der WebUI, der Aufruf der Schulkonsole im Browser und der Authentifizierungsversuch

2025-10-28 22:46:16,200 INFO    : Loading config from /etc/ajenti/config.yml
2025-10-28 22:46:16,208 INFO    : Loading users from /etc/ajenti/users.yml
2025-10-28 22:46:16,210 INFO    : Loading smtp config from /etc/ajenti/smtp.yml
2025-10-28 22:46:16,212 INFO    : Loading tfa config from /etc/ajenti/tfa.yml
2025-10-28 22:46:16,212 INFO    : Ajenti Core 2.2.11
2025-10-28 22:46:16,212 INFO    : Master PID - 871222
2025-10-28 22:46:16,212 INFO    : Detected platform: debian / Ubuntu 24.04.3 LTS
2025-10-28 22:46:16,212 INFO    : Python version: 3.12.3
2025-10-28 22:46:16,293 INFO    : Discovered 36 plugins
2025-10-28 22:46:16,325 INFO    : docker.__init__.py: docker loaded
2025-10-28 22:46:16,875 INFO    : lmn_clients.__init__.py: lmn_clients loaded
2025-10-28 22:46:17,069 INFO    : lmn_vdi_administration.__init__.py: lmn_vdi_administration loaded
2025-10-28 22:46:17,076 INFO    : lmn_vdi_dashboard.__init__.py: lmn_vdi_dashboard loaded
2025-10-28 22:46:17,079 INFO    : lmn_wireguard.__init__.py: lmn_wireguard loaded
2025-10-28 22:46:17,155 INFO    : lmn_crontab.__init__.py: lmn_crontab loaded
2025-10-28 22:46:17,167 INFO    : lmn_links.__init__.py: lmn_links loaded
2025-10-28 22:46:17,169 INFO    : samba_dns.__init__.py: samba_dns loaded
2025-10-28 22:46:17,182 INFO    : lmn_dhcp.__init__.py: lmn_dhcp loaded
2025-10-28 22:46:17,185 INFO    : lmn_nextcloud.__init__.py: lmn_nextcloud loaded
2025-10-28 22:46:17,468 INFO    : lmn.device-manager.__init__.py: lmn.device-manager loaded
2025-10-28 22:46:17,472 INFO    : lmn_landing.__init__.py: lmn_landing loaded
2025-10-28 22:46:17,496 INFO    : lmn_websession.__init__.py: lmn_websession loaded
2025-10-28 22:46:17,499 INFO    : Loaded 36 plugins
2025-10-28 22:46:17,499 INFO    : Binding to [0.0.0.0]:443
2025-10-28 22:46:17,525 INFO    : SSL enabled
2025-10-28 22:46:17,526 INFO    : New worker "restricted session" PID 871260, EUID 0, EGID 0
2025-10-28 22:46:17,527 INFO    : Worker 871260 is demoting to UID 65534 / GID 65534...
2025-10-28 22:46:17,527 INFO    : ...done, new EUID 65534 EGID 65534
2025-10-28 22:46:22,474 INFO    : 192.168.1.254 - - [2025-10-28 22:46:22] "GET /socket.io/?EIO=4&transport=polling&t=PeioL25 HTTP/1.1" 200 254 0.002494
2025-10-28 22:46:22,700 INFO    : 192.168.1.254 - - [2025-10-28 22:46:22] "POST /socket.io/?EIO=4&transport=polling&t=PeioL9Z&sid=ngydgj2W2hatGhT8AAAA HTTP/1.1" 200 207 0.001898
2025-10-28 22:46:22,942 INFO    : 192.168.1.254 - - [2025-10-28 22:46:22] "GET /socket.io/?EIO=4&transport=polling&t=PeioL9Z.0&sid=ngydgj2W2hatGhT8AAAA HTTP/1.1" 200 157 0.000152
2025-10-28 22:46:23,167 INFO    : 192.168.1.254 - - [2025-10-28 22:46:23] "GET /socket.io/?EIO=4&transport=polling&t=PeioLGu&sid=ngydgj2W2hatGhT8AAAA HTTP/1.1" 200 157 0.000157
2025-10-28 22:46:23,635 INFO    : 192.168.1.254 - - [2025-10-28 22:46:23] "GET /api/core/tasks/request-update HTTP/1.1" 401 142 0.004230
2025-10-28 22:46:46,990 INFO    : 192.168.1.254 - - [2025-10-28 22:46:46] "GET / HTTP/1.1" 302 162 0.002593
2025-10-28 22:46:47,229 INFO    : 192.168.1.254 - - [2025-10-28 22:46:47] "GET /view/login/normal HTTP/1.1" 200 12512 0.005939
2025-10-28 22:46:47,548 INFO    : 192.168.1.254 - - [2025-10-28 22:46:47] "GET /resources/all.css HTTP/1.1" 200 29721 0.016491
2025-10-28 22:46:47,550 INFO    : 192.168.1.254 - - [2025-10-28 22:46:47] "GET /resources/all.vendor.css HTTP/1.1" 200 17130 0.016667
2025-10-28 22:46:47,774 INFO    : 192.168.1.254 - - [2025-10-28 22:46:47] "GET /resources/all.init.js HTTP/1.1" 200 654 0.002035
2025-10-28 22:46:47,924 INFO    : 192.168.1.254 - - [2025-10-28 22:46:47] "GET /resources/all.js HTTP/1.1" 200 94417 0.142693
2025-10-28 22:46:47,940 INFO    : 192.168.1.254 - - [2025-10-28 22:46:47] "GET /resources/all.partials.js HTTP/1.1" 200 83648 0.152087
2025-10-28 22:46:47,959 INFO    : 192.168.1.254 - - [2025-10-28 22:46:47] "GET /resources/all.vendor.js HTTP/1.1" 200 703211 0.179031
2025-10-28 22:46:48,387 WARNING : URL not found: /favicon.ico
2025-10-28 22:46:48,391 INFO    : 192.168.1.254 - - [2025-10-28 22:46:48] "GET /favicon.ico HTTP/1.1" 404 5580 0.005639
2025-10-28 22:46:48,410 INFO    : 192.168.1.254 - - [2025-10-28 22:46:48] "GET /resources/all.locale.js?lang=de HTTP/1.1" 200 24778 0.007493
2025-10-28 22:46:48,413 INFO    : 192.168.1.254 - - [2025-10-28 22:46:48] "GET /resources/all.locale.js?lang=de HTTP/1.1" 200 24778 0.010555
2025-10-28 22:46:48,414 INFO    : 192.168.1.254 - - [2025-10-28 22:46:48] "GET /api/core/sidebar HTTP/1.1" 401 142 0.010440
2025-10-28 22:46:48,414 INFO    : 192.168.1.254 - - [2025-10-28 22:46:48] "GET /api/core/sidebar HTTP/1.1" 401 142 0.010305
2025-10-28 22:46:48,414 INFO    : 192.168.1.254 - - [2025-10-28 22:46:48] "GET /api/core/identity HTTP/1.1" 200 461 0.010351
2025-10-28 22:46:48,646 INFO    : 192.168.1.254 - - [2025-10-28 22:46:48] "GET /api/core/identity HTTP/1.1" 200 461 0.002573
2025-10-28 22:46:48,669 INFO    : 192.168.1.254 - - [2025-10-28 22:46:48] "GET /socket.io/?EIO=4&transport=polling&t=PeioRRF HTTP/1.1" 200 254 0.000695
2025-10-28 22:46:48,895 INFO    : 192.168.1.254 - - [2025-10-28 22:46:48] "POST /socket.io/?EIO=4&transport=polling&t=PeioRYt&sid=e6KKbY_Zm3qAiav3AAAC HTTP/1.1" 200 207 0.000762
2025-10-28 22:46:48,896 INFO    : 192.168.1.254 - - [2025-10-28 22:46:48] "GET /socket.io/?EIO=4&transport=polling&t=PeioRYu&sid=e6KKbY_Zm3qAiav3AAAC HTTP/1.1" 200 197 0.000178
2025-10-28 22:46:49,133 INFO    : 192.168.1.254 - - [2025-10-28 22:46:49] "GET /socket.io/?EIO=4&transport=polling&t=PeioRcd&sid=e6KKbY_Zm3qAiav3AAAC HTTP/1.1" 200 157 0.000149
2025-10-28 22:46:49,136 INFO    : 192.168.1.254 - - [2025-10-28 22:46:49] "GET /api/core/tasks/request-update HTTP/1.1" 401 142 0.002047
2025-10-28 22:46:49,366 INFO    : 192.168.1.254 - - [2025-10-28 22:46:49] "GET /socket.io/?EIO=4&transport=polling&t=PeioRgF&sid=e6KKbY_Zm3qAiav3AAAC HTTP/1.1" 200 157 0.000407
2025-10-28 22:47:26,999 ERROR   : {'result': -1, 'desc': "Can't contact LDAP server", 'errno': 13, 'ctrls': [], 'info': 'Permission denied'}
2025-10-28 22:47:27,000 ERROR   : Unhandled endpoint error at /api/core/auth
2025-10-28 22:47:27,005 INFO    : 192.168.1.254 - - [2025-10-28 22:47:27] "POST /api/core/auth HTTP/1.1" 500 3782 0.008791

Das Testskript habe ich in verschiedenen Konstellationen ausgeführt:

  1. unverändert → keine Fehlermeldung
  2. Alternative mit direkter Angabe von binddn und bindpwd
    egal mit welchem Binduser → keine Fehlermeldung
  3. Alle Kombinationen der Optionen habe ich ausprobiert → keine Fehlermeldung
  4. LDAP-Port gegen 389 getauscht → keine Fehlermeldung

Hab mal das Logging des Samba-AD/DC hochgeschraubt und mir die Authentifizierungsversuche anzeigen lassen.
Bei jedem Ausführen Deines Testskripts konnte ich mit dem jeweiligen Benutzer einen Eintrag im Log sehen. Beim Authentifizierungsversuch über die WebUI jedoch nicht. D. h. es wird wohl keine Verbindung zum LDAP aufgebaut.

Dann hab ich noch die WebUI nicht als Daemon gestartet sondern direkt im Terminal mit:

/opt/linuxmuster/bin/python3 /opt/linuxmuster/bin/ajenti-panel --stock-plugins --plugins /usr/lib/linuxmuster-webui/plugins -v --log debug

Dort kam dann vor den bereits bekannten Fehlermeldungen, die nach dem Authentifizierungsverusch über die WebUI in der Box Serverfehler ausgegeben werden noch folgende Fehlermeldung:

Traceback (most recent call last):                                                                            
  File "/opt/linuxmuster/lib/python3.12/site-packages/gevent/pywsgi.py", line 1111, in handle_one_response    
    self.run_application()                                                                                    
  File "/opt/linuxmuster/lib/python3.12/site-packages/aj/wsgi.py", line 28, in run_application                
    super(WebSocketHandler, self).run_application()                                                           
  File "/opt/linuxmuster/lib/python3.12/site-packages/gevent/pywsgi.py", line 1057, in run_application        
    self.result = self.application(self.environ, self.start_response)                                                                                                                                                       
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                                       
  File "/opt/linuxmuster/lib/python3.12/site-packages/engineio/middleware.py", line 74, in __call__                                                                                                                         
    return self.wsgi_app(environ, start_response)                                                             
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                                                           
  File "/opt/linuxmuster/lib/python3.12/site-packages/aj/http.py", line 44, in dispatch                                                                                                                                     
    if not _validate_origin(env):                                                                                                                                                                                           
           ^^^^^^^^^^^^^^^^^^^^^                                                                              
  File "/opt/linuxmuster/lib/python3.12/site-packages/aj/http.py", line 21, in _validate_origin               
    valid_origin = aj.config.data['trusted_domains'] + [f'{protocol}://{env["HTTP_HOST"]}']                   
                                                                        ~~~^^^^^^^^^^^^^                      
KeyError: 'HTTP_HOST'                                                                                                                                                                                                       
2025-10-28T22:08:52Z {'REMOTE_ADDR': 'EINE_PRIVATE_IP, 'REMOTE_PORT': '60848', (hidden keys: 23)} failed with KeyError

Kannst Du damit vielleicht etwas anfangen?

Viele Grüße
Jürgen

Hallo @juergen,

Dumme Frage: hast du die Webui anders installiert als der normalen Weg ? Oder durch einen Proxy ?

Ich verstehe nicht ganz, warum HTTP_HOST hier nicht vorhanden ist, aber du kannst auch einfach die Zeile

valid_origin = aj.config.data['trusted_domains'] + [f'{protocol}://{env["HTTP_HOST"]}']

durch

valid_origin = aj.config.data['trusted_domains']

oder

valid_origin = aj.config.data['trusted_domains'] + ['https://10.0.0.1:8000'] # oder URL von der Webui

in /opt/linuxmuster/lib/python3.12/site-packages/aj/http.py ersetzen (und dann die Webui neu starten).

Gruß

Arnaud

Hallo Arnaud,

bitte entschuldige die späte Antwort, ich kam in den letzten Tagen leider nicht zum Testen.

Wir haben die Webui ganz normal über das Repository ohne Proxy installiert.

Nach dem Austauschen der besagten Zeile durch

valid_origin = aj.config.data['trusted_domains']

und danach durch

valid_origin = aj.config.data['trusted_domains'] + ['https://10.0.0.1:8000']

kam oben rechts lediglich ein Server- und Authentifizierungsfehler-Pupup, jedoch ohne Traceback.

Dann habe ich in der Funktion _validate_origin alle Anweisungen auskommentiert, damit sie immer True zurückliefert.
Beim Anmeldevorgang in der Webui erscheint dann wieder der im Eingangspost genannte Fehler

Ldap server down: {'result': -1, 'desc': "Can't contact LDAP server", 'errno': 13, 'ctrls': [], 'info': 'Permission denied'}

mit dem selben Traceback.

Viele Grüße
Jürgen

Hallo Jürgen,

Ich habe mal noch lang probiert zu verstehen, was los ist, ich habe gerade keine Idee, außer evtl:

  • in auth.log oder in syslog anschauen, ob etwas da steht,
  • tcpdump nutzen, um die Anfragen auf Port 636 zu verfolgen,
  • hat der Server mehrere IPs ? gibt es evtl ein FW da zwischen ?
  • eine besondere Regel von selinux ?

Gruß

Arnaud