====== Apache amb DNIe ====== Configurar el servidor web (en aquest cas Apache) per a que validi certificats de confiança (en aquest cas del DNIe) és una tasca important en les mesures de seguretat i autenticació de l'administració pública, i pot esdevenir-ho també en un futur per a la gestió privada. L'administració pública necessita uns estàndards molt alts de seguretat, sobretot en el què respecta a autenticació i validació de la identitat de l'usuari. En realitat el que realitzarem serà una [[https://www.openlogic.com/blog/mutual-authentication-using-apache-and-web-client|autenticació mútua entre servidor i client]], essent necessaris tant a l'un com a l'altre la configuració dels certificats de la CA (Certificate Authority, pel nostre cas el "AC RAIZ DNIE 2") i, per part del client, el certificat signat per aquesta mateixa CA (present dins del DNIe). {{ dnie.png?400 }} Referències i ampliacions: * [[https://smallstep.com/hello-mtls/doc/server/nginx|Autenticació mútua amb Nginx]]. Descàrregues: - [[https://www.dnielectronico.es/PortalDNIe/PRF1_Cons02.action?pag=REF_1100|Software client DNIe]]. - [[https://www.dnielectronico.es/PortalDNIe/PRF1_Cons02.action?pag=REF_077|Certificats arrel de la l'autoritat de certificació del DNIe]]. {{tag> ciberseguretat apache webserver servidorweb www web http https serveis #FpInfor #Daw #DawMp08 #DawMp08Uf01 #Asix #AsixMp08 #AsixMp08Uf02 #Ciber #CiberMp03 #Ceti #CetiMp03 }} \\ ===== Configuració del client ===== ==== Disposar de certificats vàlids al DNIe ==== Primer de tot caldrà que tingueu el DNIe amb els certificats vàlids. Per solventar-ho cal que aneu a una **Commissaria de la Policía Nacional** i us assegureu que renoveu els certificats i coneixeu el vostre PIN. És molt important tenir el PIN clar perquè les //smart cards// es bloquegen als 3 errors d'accés. Si es donessin aquests 3 accessos erronis caldria tornar a la Comissaria per renovar els certificats. ==== Lector de targetes ==== Necessitarem un lector de targetes que funcioni amb el DNIe. [[https://zoweetek.com/product-item/smart-card-reader-zw-12026-1/|Aquest lector de targetes de Zoweetek]], per exemple, sabem que és compatible amb el DNIe tant per a GNU/Linux com per a Windows i Mac. Pot ser que el lector de //smart cards// no estigui habilitat. Per comprovar-ho en GNU/Linux podem fer: $ pcsc_scan Si el servei no està instal·lat, es pot fer amb: $ sudo apt install pcsc-tools pcscd Si continua sense funcionar ''pcsc_scan'', es pot activar amb: $ sudo systemctl enable pcscd $ sudo systemctl start pcscd $ pcsc_scan \\ ==== Resolució client en Windows ==== Per a Windows l'executable descarregat a la web del DNIe realitza aquestes passes més o menys automàticament si no hi ha cap error. [[https://www.dnielectronico.es/PortalDNIe/PRF1_Cons02.action?pag=REF_1100|Àrea de descàrregues a la pàgina oficial del DNIe]] per als diferents SO. \\ ==== Resolució client en Ubuntu 22.04 ==== A la pàgina de descàrregues del DNIe es mostra el paquet DEB per a versions fins la Ubuntu 21.10, però no la darrera Ubuntu 22.04 LTS. El problema, [[https://askubuntu.com/questions/1409351/ubuntu-22-04-firefox-unable-to-load-module|segons aquest post]], és la versió snap (enlloc de la clàssica APT) de Firefox que Canonical fa servir des d'aquesta versió. Per solventar-ho, podem desinstal·lar Firefox i instal·lar la versió [[https://mzl.la/3diKQVW|Firefox ESR (Extended Support Release)]] més estable i que actualment és un estàndard d'estabilitat en distribucions com Debian. Desinstal·lem el Firefox de snap (pot trigar una mica, mira de tancar totes les pantalles de Firefox primer): # snap remove firefox Afegim els repositoris de mozillateam i instal·lem firefox-esr: # apt install software-properties-common -y # add-apt-repository ppa:mozillateam/ppa # apt install firefox-esr Si es paralitza la instal·lació, tanca la finestra de Firefox que s'ha obert. Ens obriria un breu tutorial d'instal·lació dels certificats del DNIe, però de vegades no apareix i ja l'he copiat aquí a la següent secció. Afegim un enllaç simbòlic per facilitar la comanda ''firefox'': # ln -s /usr/bin/firefox-esr /usr/bin/firefox Ara ja podem seguir i instal·lar el package DEB de la web oficial del DNIe. === Navegador i certificats DNIe === Caldrà que tinguem la màquina client i el navegador configurats adientment per poder utilitzar el DNIe: [[https://www.dnielectronico.es/PortalDNIe/PRF1_Cons02.action?pag=REF_1100|Àrea de descàrregues a la pàgina oficial del DNIe]] per als diferents SO. Bàsicament la instal·lació té aquestes passes: - Instal·lar els //drivers// necessaris per accedir al lector de targetes. Normalment es fa d'aquesta manera i hauria de mostrar instruccions de com procedir amb les següents passes per completar la instal·lació:sudo dpkg -i arxiu.deb sudo apt install -f - Configurar la llibreria PKCS#11 al Firefox que permeti introduir el PIN a l'accedir al DNIe. Normalment seria (revisar si coincideix amb les instruccions):Firefox > Paràmetres > Privadesa i seguretat > Certificats > Dispositius > Carrega /usr/lib/libpkcs11-dnie.soSi et surt l'error: No s'ha pogut afegir el mòdul Ves a la secció anterior de "Resolució amb Ubuntu 22.04" per solucionar-ho. - Instal·lar el certificat arrel del DNIe al navegador local per tal que doni per bo l'accés al certificat del DNIe (no ve instal·lat per defecte):Firefox > Paràmetres > Privadesa i seguretat > Certificats > Mostra els certificats - Comprova que tens instal·lat el certificat local del DNI anant als certificats del //browser// comprovant que teniu instal·lat el certificat de la "DIRECCION GENERAL DE LA POLICIA -> AC DNIE". Si no hi és, importa'l clicant "Importa" i carrega l'arxiu:/usr/share/libpkcs11-dnie/AC RAIZ DNIE 2.crt Per acabar de comprovar que el client funciona correctament, proveu verificar-ho a: * [[https://www.sede.fnmt.gob.es/certificados/persona-fisica/verificar-estado|Pàgina de verificació de la FNMT]]. * [[https://dnie.ieti.cat|Site dnie.ieti.cat]] on hem implementat exactament la pràctica que es proposa aquí. \\ ===== Configurar el servidor ===== Podem fer la pràctica en un servidor públic (Cloud) però també funciona en un servidor local (VM). Podem fer una instal·lació en local, és la manera més senzilla. Encara que els certificats del HTTPS siguin autofirmats, podem realitzar l'autenticació de client requerint el DNIE. També és recomanable (no imprescindible) engegar una màquina Vagrant per aïllar la instal·lació i no enredar les configuracions de la màquina //host//. Crea el següent ''Vagrantfile'' en una carpeta per a la teva VM: # -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.box = "ubuntu/jammy64" config.vm.hostname = "ubudnie" config.vm.network "private_network", ip: "192.168.33.10" config.vm.provider "virtualbox" do |vb| vb.name = "ubudnie" vb.gui = false vb.memory = "2048" end end Entrem a la VM amb: $ vagrant ssh Fem instal·lació bàsica d'Apache i PHP i activem SSL: - Engegar la VM amb el Vagranfile anterior. - Assignar-li una IP convenient (potser la que té ja us serveix). - Instal·lar Apache2 i PHP. - Activar //mod_ssl// d'Apache. - Activar la //site// ''default-ssl.conf'' La pràctica es pot muntar perfectament en la màquina local. Tot i això, perquè sigui operativa de veritat ha d'estar en un servidor públic i amb certificats vàlids. Així, recomanem aquestes passes: - Engegar una màquina al núvol (preferentment amb Ubuntu 22.04) accessible, al menys, als ports 80 i 443. - Assignar-li una IP fixa (elastic IP en cas de AWS). - Apuntar-hi un domini propi. - Instal·lar Apache2 i PHP. - Obrir els ports 80 i 443 (en cas que tingui firewall del proveidor o del propi SO com UFW). - Activar mod_ssl d'Apache. - Configurar certificats HTTPS correctament. La manera més senzilla és utilitzar Certbot de Let's Encrypt. Si arribes aquí, ja tenim el server preparat per activar autenticació via DNIe al teu site. Si estàs fent servir alguna mena de **proxy invers com Cloudflare** per protegir la teva site, pensa que **els certificats de client no funcionaran**. Segurament cal alguna configuració extra dins el teu proveïdor per redirigir les peticions de certificat de client. Per tant, si tens configurat Cloudflare, habilita un subdomini (per exemeple dnie.domini.cat) i **desactiva-hi el proxy invers** per tal de que la comunicació sigui directa amb el server. \\ ==== Documentació oficial (obsoleta!) per a Apache ==== Aquí s'explica la [[https://www.openlogic.com/blog/mutual-authentication-using-apache-and-web-client|doble autenticació mútua entre servidor i client]]. En aquesta documentació de INTECO disposem d'una guia per a configurar Apache amb els certificats necessaris per al DNIe, tot i que caldran algunes modificacions i actualitzacions: - [[https://docplayer.es/3217884-Dia-2-taller-autenticacion-web-con-dnie.html|Taller INTECO PDF online]]. - {{dia_2_taller_autenticación_web_con_dnie.pdf}} descarrega't el PDF de bytes.cat. **ULL: aquesta configuració és obsoleta. Veure més avall l'actualitzada**. Ho deixem com a documentació de les fonts. El què es proposa a la documentació del DNIe és el què segueix. # Configuracio DNIe # ULL: aquesta configuració és obsoleta. Veure més avall l'actualitzada # Certificado raiz DNIe SSLCACertificateFile "/etc/ssl/certs/AC RAIZ DNIE 2.crt" # El cliente debe autenticarse obligatoriamente con el certificado SSLVerifyClient require # Nivel máximo de profundidad (según infraestructura actual, 2) SSLVerifyDepth 2 # Exportar contenido de certificados y certificados (para poder usarlos con PHP) SSLOptions +StdEnvVars +ExportCertData Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all La directiva més important és la que exigeix el certificat a l'usuari que intenta entrar en aquest ''Directory'': SSLVerifyClient require Per saber més d'aquesta directiva d'Apache i les seves opcions [[https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslverifyclient|consulta la doc oficial de SSLVerifyClient]]. Canvis que cal fer: - Treure la ''SSLCACertificateFile'' del nivell de ''Directory'' i posar-ho al nivell de ''VirtualHost''. Apache ara no admet diferents certificats per directori (només un per VirtualHost). - Canviar el ''Directory'' per ''Location'' , tal i com recomana fer-ho Apache2. Per exemple, creeu una zona reservada a ''Location /zona-privada''. - Pujar ''SSLOptions'' i ''Options'' també a nivell de VirtualHost (tot i que això no és imprescindible). \\ ==== Troubleshooting ==== Un error que ens pot sorgir és que ens doni un 403 FORBIDDEN "Cannot perform Post-Handshake Authentication." En aquest cas és per una incompatibilitat amb la implementació del protocol de seguretat amb el navegador. Per solventar-lo, només cal afegir aquesta directiva per forçar a fer servir el protocol TLSv1.2: SSLProtocol -all +TLSv1.2 \\ ==== Configuració final Apache2 ==== Com ja hem dit, podem realitzar aquesta instal·lació en local, tot i que és més interessant realitzar-la en un servidor públic. Recorda que per configurar [[Apache2 en Debian Ubuntu]] hem de situar l'arxiu .conf a la carpeta ''sites-available'' i habilitar la //site// amb ''a2ensite''. Els certificats vàlids estan a la carpeta ''/etc/ssl/certs'', en //symbolic links//. És interessant destacar que afegir l'arxiu a la carpeta i emprar la directiva ''[[https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslcacertificatepath|SSLCACertificatePath]]'' no funcionarà, a la documentació s'explica que cal seguir un //symbolic link// amb un format de hash concret. Necessitem [[https://www.dnielectronico.es/PortalDNIe/PRF1_Cons02.action?pag=REF_077|descarregar els certificats arrel de l'Autoritat de Certificació (AC) del DNIe]] i configurar l'accés amb la directiva ''SSLCACertificateFile''. La configuració que emprarem serà mitjançant l'arxiu ''/etc/ssl/certs/ca-certificates.crt'', on estan tots els certificats concatenats seguidament, i amb la directiva ''[[https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslcacertificatefile|SSLCACertificateFile]]''. El certificat de CA de la FNMT ja hi és per defecte, però no el del DNIe. Per tant, el descarreguem, descomprimim i annexem a ''ca-certificates.crt'' per tal d'habilitar-ho: # cd /etc/ssl/certs # wget https://www.dnielectronico.es/ZIP/ACRAIZ-DNIE2.zip # unzip ACRAIZ-DNIE2.zip # cat "AC RAIZ DNIE 2.crt" >> /etc/ssl/certs/ca-certificates.crt Fixeu-vos que l'arxiu de certificats el configurem amb la directiva: SSLCACertificateFile /etc/ssl/certs/ca-certificates.crt Finalment, la configuració d'Apache per a validació del DNIe ens quedarà com segueix. ServerAdmin webmaster@localhost #ServerName localhost DocumentRoot /var/www/html LogLevel debug ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined SSLEngine on # Certificats per validar HTTPS (aquests son autofirmats) SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key # Configuracio DNIe SSLCipherSuite HIGH:MEDIUM:-SSLv2 SSLProtocol -all +TLSv1.2 # Arxiu amb tots els certificats (cal afegir-hi el "AC RAIZ DNIE 2.crt") SSLCACertificateFile /etc/ssl/certs/ca-certificates.crt # Exportar contenido de certificados (para poder usarlos con PHP) SSLOptions +StdEnvVars +ExportCertData Options Indexes FollowSymLinks MultiViews SSLVerifyClient require #SSLVerifyClient optional_no_ca # Nivel máximo de profundidad (según infraestructura actual, 2) SSLVerifyDepth 2 AllowOverride None Order allow,deny allow from all SSLOptions +StdEnvVars SSLOptions +StdEnvVars \\ ==== Accedint a les dades del certificat amb PHP ==== Abans de fer el codi, recordeu que cal instal·lar PHP al servidor: $ sudo apt install libapache2-mod-php A les variables supraglobals trobaràs les dades que el client transmet al servidor, en particular les de ''$_SERVER'' que comencen per ''SSL_...'', com per exemple ''$_SERVER['SSL_CLIENT_S_DN']''. Aquestes variables les aconseguim capturar dins el nostre llenguatge de programació (en aquest cas PHP) mitjançant la directiva d'Apache: SSLOptions +StdEnvVars +ExportCertData Si no està activada aquesta directiva no podrem veure les dades del client. A aquesta [[http://web.archive.org/web/20160324032639/http://doku.locolandia.net/howto/apache-dnie-auth|web hi ha alguns exemples]] de com escanejar totes les variables supragrobals. Les variables que podem fer servir son: - ''$_SERVER['SSL_CLIENT_S_DN']'' : les dades del DNIe (nom, cognoms, número del DNI, etc.). Caldrà fer algun //parse// extra per aïllar les variables adientment (per exemple, extreure el número del DNI). - ''$_SERVER['SSL_CLIENT_S_DN_G']'' : el nom de pila. - ''$_SERVER['SSL_CLIENT_S_DN_S']'' : el 1r cognom. - ''$_SERVER['SSL_CLIENT_CERT_CHAIN_0']'' : issuer certificate - ''$_SERVER['SSL_CLIENT_CERT']'' : client certificate Amb aquest codi pode examinar totes les variables que ens arribien dins l'array supraglobal ''$_SERVER'':

Portal DNIe


\n\n"; echo "\n\n"; foreach( $_SERVER as $key => $val ) { echo "\n\n"; } echo "\n
$key$val
\n"; ?>
\\ ==== Comprovació de revocació OCSP ==== Amb la comprovació OCSP el què fem és consultar la base de dades de la pròpia CA (autoritat certificadora, la seu del DNIe) per comprovar que el certificat que ens arriba no hagi estat revocat. És una important passa de seguretat. El resultat de la consulta OCSP hauria de ser: **good**, **revoked** o **unknown**. En aquestes pàgines tenim exemples de com fer una query OCSP (a ocsp.dnie.es) per conèixer l'estat del certificat utilitzat, ja que podria estar revocat: - [[http://web.archive.org/web/20160324032639/http://doku.locolandia.net/howto/apache-dnie-auth|Wiki locolandia]] (còpia a archive.org) - {{dia_2_taller_autenticación_web_con_dnie.pdf|Turorial INTECO DNIe}} página 10. La 1a funciona, però cal corregir un petit error en la línia de la query que es fa mitjançant OCSP. Investiga què és el què pot fallar (la manera més fàcil és activant els missatges de error d'Apache a php.ini i mostrant les variables intermitges. Mostra també la query ''openssl'' per veure què és el que fem executar a la //shell// i excecuta-la manualment en una //shell// a part per esbrinar quin problema ens estava succeint. \\ ==== Altres certificats ==== Perquè ens funcioni amb diversos tipus de certificats com idCAT, hisenda, etc. podem fer servir l'arxiu amb tots els certificats agrupats que porta Apache, al qual afegirem el del DNIe, que per defecte no ve inclòs. # cd /etc/ssl/certs # cat AC_RAIZ_DNIE_2.crt >> ca-certificates.crt I canviarem la línia de l'anterior arxiu de configuració on diu: SSLCACertificateFile /etc/ssl/certs/AC_RAIZ_DNIE_2.crt per: SSLCACertificateFile /etc/ssl/certs/ca-certificates.crt