To enable HTTP Strict Transport Security in lighttpd use the following config:
server.modules += ( "mod_setenv" )
$HTTP["scheme"] == "https" {
setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=31536000")
}
The max-age value is in seconds. Use 31536000 for 12 months or 63072000 for 24 months.
Adding includeSubdomains means that subdomains of the main domain should also be accessed using SSL.
Dieses Beispiel führt ein Upgrade der HTTP-Verbindungen auf HTTPS durch (HSTS und CSP: /etc/lighttpd/lighttpd.conf):
server.modules += ( "mod_setenv" )
$HTTP["scheme"] == "https" {
setenv.add-response-header = ( "Strict-Transport-Security" => "max-age=31536000",
"Content-Security-Policy" => "default-src https: data: 'unsafe-inline' 'unsafe-eval' always; upgrade-insecure-requests" )
}
SSL-Cipher auflisten:
> openssl ciphers -V > openssl ciphers | tr -s ':' '\n' > openssl ciphers -V 'EECDH+aRSA+AES256:!SSLv3' > openssl ciphers -V 'EECDH+aRSA+AES256:ECDHE-RSA-AES128-GCM-SHA256:!SSLv3' > openssl ciphers -V 'EECDH+aRSA+AES256:ECDHE-RSA-AES128-GCM-SHA256' > openssl ciphers -V 'TLSv1+HIGH:!LOW:!3DES:!MD5:!RC4:!DSS:!PSK:!EXP:!SRP:!aNULL:!eNULL:!SSLv2:@STRENGTH'
> vi /etc/lighttpd/conf-enabled/10-ssl.conf
...
##
## Documentation: /usr/share/doc/lighttpd-doc/ssl.txt
##
#### SSL engine
$SERVER["socket"] == "0.0.0.0:443" {
ssl.engine = "enable"
ssl.pemfile = "/etc/lighttpd/ssl/domain.de.pem"
ssl.ca-file = "/etc/lighttpd/ssl/intermediate.domain.de.crt"
ssl.use-sslv2 = "disable"
ssl.use-sslv3 = "disable"
ssl.honor-cipher-order = "enable"
ssl.use-compression = "disable"
ssl.cipher-list = "EECDH+aRSA+AES256:ECDHE-RSA-AES128-GCM-SHA256:!SSLv3"
ssl.disable-client-renegotiation = "enable"
$HTTP["useragent"] =~ ".*MSIE (9|10)\..*" {
server.max-keep-alive-requests = 0
}
}
...
viele HTML-Aufruf-Methoden können gefährlich sein, deshalb lassen wir mit diesem Teil nur "GET", "POST" und "HEAD" zu:
> vi /etc/lighttpd/lighttpd.conf
...
$HTTP["request-method"] !~ "^(GET|POST|HEAD)$" {
url.access-deny = ("")
}
...
Das kann mit diesem SED-Kommando ganz leicht eingestellt werden:
> sed -i 's/\$HTTP\["request-method"\] .*/$HTTP["request-method"] !~ "^(GET|POST|HEAD)$" {/' /etc/lighttpd/lighttpd.conf
http://redmine.lighttpd.net/projects/1/wiki/DebugVariables
um Fehler zu finden ist es oft gut, ins Log zu sehen, damit im Log auch genug zu sehen ist, muss debug.log-request-header eingeschaltet werden:
> vi /etc/lighttpd/lighttpd.conf
...
debug.log-request-header = "enable"
server.errorlog-use-syslog = "enable"
#server.errorlog = "/var/log/lighttpd/error.log"
accesslog.format = "premiumsim.de %V %h %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
accesslog.use-syslog = "enable"
#accesslog.filename = "/var/log/lighttpd/access.log"
...
Leider gibt es für LighttpD kein Modul um die Passwortabfrage auf eine DB zu realisieren, wie man es vom Apache kennt. Um eine derartige Funktionalität in LighttpD umzusetzten, muss man ein entsprechendes LUA-Skript einbinden.
Die Dateien, die Passwörter enthalten, dürfen nicht für die Welt lesbar sein!
> chown 33:33 /etc/lighttpd/sha512crypt.php /etc/lighttpd/mysql_auth.lua > chmod 0640 /etc/lighttpd/sha512crypt.php /etc/lighttpd/mysql_auth.lua
hier muß die IP ("192.168.2.99") des Web-Servers eingetragen werden:
#
$HTTP["host"] =~ "192.168.2.99" {
magnet.attract-physical-path-to = ( "/etc/lighttpd/mysql_auth.lua" )
}
-- vim: set ts=4 sw=4 sts=4 noai noet: --[[ MySQL-Auth - IQ lighttpd-mod-magnet lua-socket lua-sql-mysql *************************** 1. row *************************** id: 1 login: Fritz password: a8e13417253337017fb29cbe1a647bba2d7dca95b232f70f782bd64da49855606d122e5715d6a63754d88d1ea3fe561af26260fedd7b2425044c7e565fa1dfa0 ]] --[[ https://redmine.lighttpd.net/projects/lighttpd/wiki/AbsoLUAtion#Do-basic-HTTP-Auth-against-a-MySQL-DBTable Known Problems: This Script is blocking!!! Lighttpd will hang, if there are MySQL connection problems. Additionally, a whole new MySQL Connection is created with every request! So you shouldn't use this on High-Traffic Sites. Passwords are stored plain in MySQL - well, easy to fix. Look for MySQL's PASSWORD function.... ]] -- nur "/geheim.php" soll passwortgeschützt sein if ( string.format('%s', lighty.env["uri.path"]) == "/geheim.php" ) then -- Force https if (lighty.env["uri.scheme"] == "http") then lighty.header["Location"] = "https://" .. lighty.env["uri.authority"] .. lighty.env["request.uri"] return 302 end --[[ Config Variables ]] local dbConf = {} dbConf.database = 'authdb' dbConf.username = 'dbuser' dbConf.password = 'geheim' dbConf.hostname = '192.168.2.10' dbConf.port = "3306" --[[ dbConf.users_table = "dealer_logins" dbConf.col_user = "login" dbConf.col_pass = "password" ]] --[[ Requires ]] -- Debian package: liblua5.1-socket2 -- required for Base64 De-/encoding. See: http://w3.impa.br/~diego/software/luasocket/home.html require("mime") -- Debian package: liblua5.1-sql-mysql-2 -- Lua Mysql Driver luasql = require("luasql.mysql") --[[ Function to send HTTP-Auth request ]] function doAuth() lighty.header["WWW-Authenticate"] = string.format('Basic realm="%s"', lighty.env["uri.authority"]) return 401 end --[[ Function to check Auth Creds against MySQL Database ]] local env = assert(luasql.mysql()) local con = assert(env:connect ( dbConf.database ,dbConf.username ,dbConf.password ,dbConf.hostname ,dbConf.port )) function checkAuthMySQL(user,pass) local res = con:execute(string.format([[ SELECT login, password FROM `dealer_logins` WHERE `login` = '%s' AND `password` = '%s' ]], user, pass) ) -- Die Tabelle wir in ein Array gespeichert local row = res:fetch ({}, "a") -- print(type(row)) -- close everything -- res:close() -- already closed because all the result set was consumed con:close() -- env:close() if (not row) then return false else lighty.req_env['REMOTE_USER'] = user return true end end -- MAIN --[[ Check for Authorization Header and force Basic Auth if not set. ]] if (not lighty.request.Authorization) then return doAuth() end --[[ Header found: check string for "Basic" and base64 encoded username & password - upb = User Password Base64 encoded ]] _, _, upb = string.find(lighty.request.Authorization, "^Basic%s+(.+)$") up = mime.unb64(upb) -- Base64 Decode _, _, username, password = string.find(up, "^(.+):(.+)$") -- split by ":" to get username and password supplied -- ============================================================================= -- In der DB steht das Passwort nicht im klartext drin, sondern verschlüsselt -- deshalb muss auch der Passwort-Hash und nicht das Passwort verglichen werden. -- -- hier wird aus dem Passwort der Passwort-Hash generiert -- -- /var/www/webauftritt/libs/WebServices/Ovp/Authentication/Encrypt.php local start = ("/usr/bin/php /etc/lighttpd/sha512crypt.php " .. password) datei = assert (io.popen (start)) pwhash = datei:read ("*l") -- read one line -- ============================================================================= if (not checkAuthMySQL(username, pwhash)) then return doAuth() end end -- return nothing to proceed normal operation return
Leider gibt es nur für eine SHA256-Verschlüsselung eine native LUA-Umsetzung. Für SHA512 müssen wir uns eines externen Programmes (in diesem Fall ein PHP-Skript) bedienen.
Der Salz-hash aus der Live-Umgebung ⇒ '<decrypt>U2FsdGVkX19AL/PUlfXxQQgDKgzZzAgiqTCFVCoKZUc=</decrypt>';
<?php $salt = 'Salz-hash'; echo hash('sha512', $salt . $argv[1]); ?>