{"id":2435,"date":"2017-11-08T06:08:01","date_gmt":"2017-11-08T06:08:01","guid":{"rendered":"https:\/\/esferas.org\/msqlu\/?p=2435"},"modified":"2017-11-20T12:03:50","modified_gmt":"2017-11-20T12:03:50","slug":"sftp-y-chroot-trabajando-juntos","status":"publish","type":"post","link":"https:\/\/esferas.org\/msqlu\/2017\/11\/08\/sftp-y-chroot-trabajando-juntos\/","title":{"rendered":"sftp y chroot trabajando juntos"},"content":{"rendered":"<p>Ayer tuve que enfrentarme a uno de esos problemas t\u00e9cnicos que hab\u00eda aparcado tiempo atr\u00e1s, un poco defraudado cuando lo encontr\u00e9 por primera vez, y que ya puedo decir que funciona y entiendo.<\/p>\n<p><!--more--><\/p>\n<p>El problema consist\u00eda en lo siguiente: la empresa va a contratar la instalaci\u00f3n de un programa web a una persona externa. \u00c9sta necesita acceso libre a ciertas carpetas que, al mismo tiempo, tienen que ser accesibles por el servidor web.<\/p>\n<p>El programa se llama <em>prestashop<\/em> y el entorno de trabajo una m\u00e1quina Debian con Apache como servidor de p\u00e1ginas y programas.<\/p>\n<h3>Acceso seguro a una parte del \u00e1rbol de archivos<\/h3>\n<p>Lo primero es crear una cuenta de usuario en el sistema lo m\u00e1s limitada posible.<\/p>\n<pre class=\"lang:sh decode:true\">$ sudo adduser --no-create-home --home \/tmp --shell \/bin\/false --ingroup www-data prestashop\r\n...\r\n$ getent passwd prestashop\r\nprestashop:x:1001:33:Instalador Prestashop,,,:\/tmp:\/bin\/false\r\n$ \r\n<\/pre>\n<p>Despu\u00e9s creamos un directorio con propiedad completa de root (toda la ruta) y donde anclaremos las conexiones entrantes v\u00eda <em>sftp<\/em> del grupo del usuario.<\/p>\n<pre class=\"lang:default decode:true\">$ sudo install -d -o root -g root -m 0755 \/chroot\/prestashop<\/pre>\n<p>Y, por \u00faltimo, toca configurar el servidor <em>sshd<\/em> para que acepte conexiones <em>sftp<\/em> limitadas al grupo del usuario especial:<\/p>\n<pre class=\"lang:default decode:true\">Subsystem sftp \/usr\/lib\/openssh\/sftp-server -u 0002\r\n\r\nUsePAM yes\r\nMatch Group www-data\r\n        ChrootDirectory \/chroot\r\n        AllowTCPForwarding no\r\n        X11Forwarding no\r\n        ForceCommand internal-sftp\r\n<\/pre>\n<p>Esto es:<\/p>\n<ol>\n<li>Habilitamos el servidor interno <em>sftp<\/em> (con la m\u00e1scara de usuario intentando que sea 0002).<\/li>\n<li>Le indicamos que emplee PAM como mecanismo de validaci\u00f3n de credenciales.<\/li>\n<li>Establecemos condiciones especiales para las conexiones del grupo <em>www-data:<\/em>\n<ol>\n<li>Enjaulamos la conexi\u00f3n al directorio <code>\/chroot<\/code> .<\/li>\n<li>Impedimos reenv\u00edos varios de X11 y TCP<\/li>\n<li>Forzamos a emplear s\u00f3lo el ftp seguro interno.<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<p>Esto funciona excepto por un detalle: la m\u00e1scara de usuario no queda correctamente establecida. Para ello vamos a a\u00f1adir una modificaci\u00f3n extra en el sistema: Editamos el archivo <code>\/etc\/pam.d\/sshd<\/code> y a\u00f1adimos la siguiente cla\u00fasula:<\/p>\n<pre class=\"lang:default decode:true\">session optional pam_umask.so umask=0002<\/pre>\n<p>La explicaci\u00f3n es que el programa <code>internal-sftp<\/code> no lee ninguno de los archivos de inicio de sesi\u00f3n (profile,login,rc,&#8230;) dado que no ejecuta ning\u00fan <em>shell<\/em>. Pero como emplea PAM para validar las credenciales s\u00ed que har\u00e1 uso de esta caracter\u00edstica.<\/p>\n<h3>Afinando el directorio inicial<\/h3>\n<p>En la configuraci\u00f3n que vemos hasta ahora el usuario se encuentra con un paso previo para acceder a su espacio: debe cambiar al directorio <em>prestashop<\/em> o usarlo como ruta relativa al transferir informaci\u00f3n. No es bonito y muestra m\u00e1s de lo que debiera.<\/p>\n<p>Mirando un poco m\u00e1s la documentaci\u00f3n que anoto al final del art\u00edculo veo que es posible enjaular la conexi\u00f3n y darle ese toque profesional; para ello es necesario indicar al servidor <em>ssh<\/em> que el directorio jaula es <em>\/chroot<\/em> pero que debe iniciar un servidor interno en el directorio de trabajo del usuario.<\/p>\n<pre class=\"lang:default decode:true\">Subsystem sftp \/usr\/lib\/openssh\/sftp-server -u 0002\r\n\r\nMatch Group www-data\r\n        ChrootDirectory \/chroot\r\n        ...\r\n        ForceCommand internal-sftp -d %u\r\n<\/pre>\n<p>Es necesario crear entonces el directorio <em>\/chroot\/prestashop<\/em> con los permisos adecuados para que el usuario pueda trabajar con comodidad:<\/p>\n<pre class=\"lang:default decode:true\">$ sudo install -d -o prestashop -g www-data -m 6760 \/chmod\/prestashop<\/pre>\n<h3>Integraci\u00f3n con el servidor web<\/h3>\n<p>Por ahora tenemos un directorio\u00a0<code>\/chroot\/prestashop<\/code> donde nuestro usuario externo puede escribir con libertad, y donde todo queda de manera predeterminada con los siguientes permisos:<\/p>\n<pre class=\"lang:sh decode:true\">root@catalogo:\/chroot# tree -pug\r\n.\r\n\u2514\u2500\u2500 [drwxrwsrwx root     www-data]  prestashop\r\n    \u2514\u2500\u2500 [drwxrwsr-x prestashop www-data]  Pruebas\r\n        \u251c\u2500\u2500 [-rw-rw-r-- prestashop www-data]  116981263_70d591cee5.jpg\r\n        \u2514\u2500\u2500 [-rw-rw-r-- prestashop www-data]  16789084225_c284b59b59.jpg\r\n\r\n2 directories, 2 files\r\nroot@catalogo:\/chroot# \r\n<\/pre>\n<p>El propietario es <em>prestashop<\/em>, el grupo es <em>www-data<\/em> y los permisos son de lectura, escritura y paso para propietario y grupo en directorios y lectura y escritura para usuario y grupo en archivos.<\/p>\n<p>Es decir, el servidor web tiene acceso para servir el contenido e incluso para modificarlo llegado el presumible caso de tener que actualizar la propia aplicaci\u00f3n.<\/p>\n<p>As\u00ed que podemos situar el directorio como el ra\u00edz para el propio servidor web, empleando la directiva <code>DocumentRoot<\/code><code><\/code>, pero \u00bf y si tenemos que integrarla en un \u00e1rbol m\u00e1s complejo ?<\/p>\n<p>Suponiendo que nuestra instalaci\u00f3n contemple varios servidores virtuales en una ra\u00edz como la siguiente:<\/p>\n<pre class=\"lang:default decode:true\">\/var\/www\/wordpress\r\n\/var\/www\/html\/server1.com\r\n\/var\/www\/html\/server2.com\r\n\/var\/www\/html\/prestashop<\/pre>\n<p>Nos encontramos con que no podemos hacer que toda la ruta previa sea propiedad exclusivamente de <em>root<\/em>, ni excluir a cualquier otro grupo del acceso a esa parte del \u00e1rbol.<\/p>\n<p>Una soluci\u00f3n pr\u00e1ctica consiste en a\u00f1adir el directorio jaula a nuestro \u00e1rbol con un montaje de tipo <a href=\"https:\/\/unix.stackexchange.com\/questions\/198590\/what-is-a-bind-mount#198591\">bind<\/a> de manera que ninguna de las dos partes sospeche nada raro.<\/p>\n<pre class=\"lang:default decode:true\">$ sudo mount -o bind \/chroot\/prestashop \/var\/www\/html\/prestashop<\/pre>\n<p>y despu\u00e9s hacerlo fijo en el arranque del sistema a\u00f1adiendo lo siguiente a la tabla de montajes (<code>\/etc\/fstab<\/code> ):<\/p>\n<pre class=\"lang:default decode:true\">\/chroot\/prestashop \/var\/www\/html\/prestashop none defaults,bind 0 1\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><code><\/code><\/p>\n<h3>Enlaces y referencias<\/h3>\n<ul>\n<li><a href=\"https:\/\/en.wikibooks.org\/wiki\/OpenSSH\/Cookbook\/File_Transfer_with_SFTP#Chrooted_login_shells\">OpenSSH\/Cookbook\/File Transfer with SFTP<\/a><\/li>\n<li><a href=\"https:\/\/serverfault.com\/questions\/584986\/bad-ownership-or-modes-for-chroot-directory-component#584993\">bad ownership or modes for chroot directory component<\/a><\/li>\n<li><a href=\"https:\/\/stackoverflow.com\/questions\/4209861\/chroot-access-to-www-folder\">chroot access to www folder<\/a><\/li>\n<li><a href=\"https:\/\/serverfault.com\/questions\/613179\/how-do-i-do-mount-bind-in-etc-fstab\">How do I do &#8216;mount &#8211;bind&#8217; in \/etc\/fstab?<\/a><\/li>\n<li><a href=\"http:\/\/sysadmin.circularvale.com\/server-config\/setting-a-umask-for-chrooted-sftp-users\/\">Setting a umask for chrooted sftp users<\/a><\/li>\n<li><a href=\"http:\/\/permissions-calculator.org\/\">Unix Permissions Calculator<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ayer tuve que enfrentarme a uno de esos problemas t\u00e9cnicos que hab\u00eda aparcado tiempo atr\u00e1s, un poco defraudado cuando lo encontr\u00e9 por primera vez, y que ya puedo decir que funciona y entiendo.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","webmentions_disabled_pings":false,"webmentions_disabled":false,"footnotes":""},"categories":[2],"tags":[75,727,728,44,726],"class_list":["post-2435","post","type-post","status-publish","format-standard","hentry","category-software","tag-apache","tag-chroot","tag-prestashop","tag-servicios-web","tag-sshd"],"_links":{"self":[{"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/posts\/2435","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/comments?post=2435"}],"version-history":[{"count":0,"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/posts\/2435\/revisions"}],"wp:attachment":[{"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/media?parent=2435"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/categories?post=2435"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/esferas.org\/msqlu\/wp-json\/wp\/v2\/tags?post=2435"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}