Verificar la configuración de Apache

Si hemos modificado la configuración de Apache y a partir de ese momento no inicia normalmente, es posible que hayamos cometido un error en alguna línea de algunos de los archivos correspondientes.

Para detectar donde está el inconveniente lo recomendable es probar la configuración. A continuación detallo la tarea en Windows:

  • Abrir el menú Inicio
  • Buscar la carpeta de Apache
  • Elegir el acceso directo Test Configuration

Si existe un error entonces se mostrará en una ventana de la línea de comandos. De lo contrario, se cerrará automáticamente.

Podemos ejecutarlo por línea de comandos conociendo la ubicación donde se encuentra instalado Apache (de manera similar se puede hacer en Linux).

Si todo funciona correctamente podremos ver algunos warnings y al final el texto:

Syntax OK

Ejemplo:

“C:\Program Files (x86)\Apache Software Foundation\Apache2.2\bin\httpd.exe” -w -t -f  “C:\Program Files (x86)\Apache Software Foundation\Apache2.2\conf\httpd.conf” -d “C:\Program Files (x86)\Apache Software Foundation\Apache2.2.”

donde se utilizan los siguientes parámetros:

  • -d <DIRECTORIO>: indica un ServerRoot alternativo
  • -f <ARCHIVO>: indica un archivo de configuración alternativo
  • -w: mantener abierta la ventana de la consola ante un error
  • -t: verificar la sintaxis de los archivos de configuración
Anuncios

Cuando Apache no inicia porque Skype se ejecuta primero

Cuando en la misma computadora conviven Skype y Apache podemos llegar a tener inconvenientes porque ambos utilizan el puerto 80 para sus conexiones. El puerto 80 es el puerto en el que por defecto Apache escucha las conexiones mientras que Skype lo utiliza como un puerto adicional o de respaldo. Contemplar que no sea un error de configuración de Apache el que no permite iniciarlo!

El problema se produce si:

  • Apache está configurado para escuchar en el puerto 80
  • Skype se inicia antes que Apache, por lo que se le asigna el puerto
  • Apache no puede iniciar

Cuando intentamos iniciar Apache desde la línea de comandos de Windows veremos el siguiente error:

net start apache2.2
El servicio de Apache2.2 está iniciándose.
El servicio de Apache2.2 no ha podido iniciarse.
Error específico del servicio: 1.
Puede obtener más ayuda con el comando NET HELPMSG 3547.

Para solucionarlo tenemos 3 alternativas:

1. Cambiar configuración de Skype

Dado que Skype utiliza el puerto 80 como un adicional, esta es la solución recomendada por mí. Para ello:

  1. Iniciar sesión en Skype
  2. Acceder al menú Herramientas > Opciones
    • o bien, presionar Ctrl + ,
  3. Abrir la opción Avanzada > Conexión
  4. Desmarcar la opción “Usar los puertos 80 y 443 para conexiones entrantes adicionales”
  5. Confirmar con Guardar

Si vemos que Skype permite las comunicaciones correctamente, y podemos iniciar el servicio de Apache, entonces damos por solucionado el problema.

Es posible que en ciertos entornos no sea una solución aplicable por políticas de seguridad de la red interna que no permitan conexiones en el puerto configurado de Skype, pero sí en alguno de los adicionales (80 o 443).

2. Cambiar el puerto de Apache

Si es posible utilizar un puerto alternativo para Apache, y nuestra aplicación web lo soporta, entonces podemos optar por esta solución. De lo contrario paramos a la última opción.

  1. Abrir con un editor de textos el archivo: conf\httpd.conf en la ubicación donde instalamos Apache
  2. Modificar en la línea que indica “Listen 80” el 80 por otro número de puerto, por ejemplo el 8080
  3. Cambiar el puerto en cada uno de los VirtualHost definidos, si es que los tenemos
  4. Reiniciar el servicio de Apache para que tome la nueva configuración.

Recordar que puede ser necesario desbloquear acceso el web a nuestro equipo, permitiendo el acceso a través del nuevo puerto en el Firewall de Windows.

3. Asegurarse que Apache inicie antes que Skype

Si el problema se debe a que ambas aplicaciones inician automáticamente con Windows, hasta el momento no conozco una forma de lograr (y asegurar) que Apache lo haga ANTES que Skype. Es por eso que en este caso extremo habrá que configurar que Skype no se inicie automáticamente con Windows y dejar que Apache sí lo haga.

Para cambiar esta configuración de Skype:

  1. Iniciar sesión en Skype
  2. Acceder al menú Herramientas > Opciones
    • o bien, presionar Ctrl + ,
  3. Abrir la opción General > Configuración General
  4. Desmarcar la opción “Ejecutar Skype al encender el equipo”
  5. Confirmar con Guardar y reiniciar el equipo

De esta manera Apache adquiere el puerto 80 y luego Skype no puede utilizarlo, pero sí podría utilizar el 443 si mantuvimos la configuración inicial.

Basado en:

http://www.ehow.com/info_12216304_apache-conflict-skype.html

Acceder a Plex desde distintos dispositivos y ubicaciones

Si contamos con Plex funcionando en un equipo del hogar, sabemos que puede ser accedido desde otros dispositivos de la red local (LAN), y en ciertos casos de manera remota (Internet), mediante una aplicación instalada en el dispositivo de las provistas por Plex:

  • Plex Mobile App
    • Soporte para iOS, Android, Windows Phone 8, and Windows 8
    • 😦 Tiene costo en cada uno.
  • Plex for connected TVs and streaming devices:
    • Soporte para Chromecast, Roku, Google TV, Smart TVs
    • 😦 Algunas tienen costo.
  • Plex Home Theater on a dedicated computer
    • Soporte para Mac y Windows
    • 😦 No tiene soporte para Linux

Es por eso que existiendo la alternativa de utilizar un simple navegador web es muy buena ya que no nos obliga a instalar nada.

La desventaja es que debemos utilizar la dirección IP del equipo donde se proveen los contenidos. Para contrarrestarla basta definir un dominio de manerla local en cada uno de los dispositivos o bien, en el servidor DNS si es que disponemos de uno en la red local.

Ahora, hay 2 situaciones que pueden molestarnos:

situación 1: no poder acceder desde el exterior (léase Internet)

situación 2: tener que definir el dominio local en cada dispositivo (por no tener DNS local) para las personas en la red local

Para tratar la situación 1, podemos crear una cuenta en Plex, desde donde vinculamos nuestro servidor Plex local y podremos accederlo desde cualquier lugar navegando por la Web. Los pasos son:

  1. Acceder a la instalación local de Plex
  2. Abrir Ajustes (icono arriba a la derecha de una llave inglesa en cruz con un destornillador)
  3. Elegir la solapa Servidor
  4. Seleccionar la opción “Conectar” de las listadas a la derecha
  5. Ingresar los datos de nuestra cuenta en Plex y presionar Ingresar
    • Si no tenemos cuenta podemos crearla ahí mismo seleccionando “Regístrate”
  6. Veremos que indica “Conectado como NOMBRE USUARIO” y “Conectando con el servidor…”. Esperamos unos segundos
  7. Se informa “El servidor está mapeado al puerto xxxxxx”

Solo basta con acceder por web a https://plex.tv/ y al presionar LAUNCH, accederemos a nuestro Plex (Si seleccionamos SERVERS podremos ver los servidores PLEX vinculados con esa cuenta)

Pero esto:

  • no soluciona la situación 2
  • obliga a registrar una cuenta en Plex
  • no permite que personas sin cuenta accedan a mi Plex (y no quiero darles los datos de mi cuenta)

Una propuesta que trata todos estos puntos es la de implementar un proxy reverso con Apache. Recuerden seguir el instructivo para configurar un proxy reverso con Apache, utilizando un dominio externo configurado mediante un DDNS y realizando la redirección de puerto en el router de la LAN. El VirtualHost tendría esta estructura:

<VirtualHost *:<PUERTO_EXTERNO> >
  ServerName <DOMINIO_EXTERNO>

  #Configuracion Proxy Reverso
  ProxyRequests Off
  ProxyPreserveHost Off
  ProxyPass / http://<PLEX_IP>:<PUERTO_PLEX>/
  ProxyPassReverse / http://<PLEX_IP>:<PUERTO_PLEX>/
</VirtualHost>

De esta manera permitiría a cualquier persona que conozca el domino externo acceder a al Plex interno. Adicionalmente la persona debería agregar un /web al final de la URL para acceder correctamente a la interfaz web.

 

La protección mínima que podemos implementar (se podría llegar a utilizar HTTPS) es aplicar una autenticación básica al VirtualHost definido:

  <Location />
    AuthType Basic
    AuthName "Restricted area"
    AuthUserFile <PATH_PASSWORDS>/.htpasswd_plex
    Require valid-user
  <Location />

donde PATH_PASSWORDS es la ubicación donde guardamos el .htpasswd que hayamos creado para el acceso a Plex (similar a proteger un directorio con htaccess).

 

Para evitar que la persona deba escribir /web al final de la URL, podemos implementar una reescritura de la URL cuando corresponda de la siguiente manera:

  1. Activar el módulo rewrite de Apache
    1. En la ubicación donde instalamos Apache, abrir con un editor de textos el archivo: conf\httpd.conf
    2. Descomentar la línea: LoadModule rewrite_module modules/mod_rewrite.so
  2. Agregar al VirtualHost definido:
  RewriteEngine on
  RewriteCond %{REQUEST_URI} !^/web
  RewriteCond %{HTTP:X-Plex-Device} ^$
  RewriteCond %{QUERY_STRING} ^$
  RewriteRule ^/$ /web/$1 [R,L]

Estas directivas agregar /web/ cuando la URL no lo contenga, no sea un dispositivo Plex el que intenta conectarse y el querystring (pares de clave valor después de ?) sea vacío.

 

Estructura completa de VirtualHost

Esta es lstructura completa del VirtualHost para acceder a un Plex de una LAN mediante la implementación de un proxy reverso con Apache, autenticación básica y reescritura de URL para acceder a la interfaz web (sin especificar /web/)

<VirtualHost *:<PUERTO_EXTERNO> >
  ServerName <DOMINIO_EXTERNO>

  #Autenticacion
  <Location />
    AuthType Basic
    AuthName "Restricted area"
    AuthUserFile <PATH_PASSWORDS>/.htpasswd_plex
    Require valid-user
  <Location />

  #Configuracion Proxy Reverso
  ProxyRequests Off
  ProxyPreserveHost Off
  ProxyPass / http://<PLEX_IP>:<PUERTO_PLEX>/
  ProxyPassReverse / http://<PLEX_IP>:<PUERTO_PLEX>/
  
  #Agregar /web/ cuando corresponda
  RewriteEngine on
  RewriteCond %{REQUEST_URI} !^/web
  RewriteCond %{HTTP:X-Plex-Device} ^$
  RewriteCond %{QUERY_STRING} ^$
  RewriteRule ^/$ /web/$1 [R,L]
</VirtualHost>

Ejemplo completo de VirtualHost

<VirtualHost *:80 >
  ServerName plex.externo.com

  #Autenticacion
  <Location />
    AuthType Basic
    AuthName "Restricted area"
    AuthUserFile c:/passwords/.htpasswd_plex
    Require valid-user
  <Location />

  #Configuracion Proxy Reverso
  ProxyRequests Off
  ProxyPreserveHost Off
  ProxyPass / http://192.168.0.5:32400/
  ProxyPassReverse / http://19.168.0.5:32400/
  
  #Agregar /web/ cuando corresponda
  RewriteEngine on
  RewriteCond %{REQUEST_URI} !^/web
  RewriteCond %{HTTP:X-Plex-Device} ^$
  RewriteCond %{QUERY_STRING} ^$
  RewriteRule ^/$ /web/$1 [R,L]
</VirtualHost>

Basado en:

http://matt.coneybeare.me/how-to-map-plex-media-server-to-your-home-domain/

http://www.dbzoo.com/blog/plex_virtual_hosting

Configurar un proxy reverso o inverso en Apache

Si contamos con un servicio web (o más) en una LAN el cual es accedido desde Internet, podemos configurar un proxy reverso o inverso para ocultar los servidores que contienen realmente las aplicaciones web. En este caso, planteamos configurar un proxy reverso HTTP en Apache.

Para poder avanzar en esta solución hay 2 puntos a tener en cuenta:

Ahora sí vamos con los pasos:

1. Activar el módulo proxy

En la ubicación donde instalamos Apache, abrimo con un editor de textos el archivo: conf\httpd.conf y descomentamos las siguientes líneas:

LoadModule proxy_module modules/mod_proxy.so
....
LoadModule proxy_http_module modules/mod_proxy_http.so

2. Configurar un VirtualHost

Debemos crear un VirtualHost con la configuración básica actuar de proxy reverso:

<VirtualHost *:<PUERTO_EXTERNO> >
  ServerName <DOMINIO_EXTERNO>

  ProxyRequests Off
  ProxyPreserveHost Off
  ProxyPass /<PATH_EXT>/ http://<DOMINIO_INTERNO>:<PUERTO_INTERNO>/<PATH_INT>/
  ProxyPassReverse /<PATH_EXT>/ http://<DOMINIO_INTERNO>:<PUERTO_INTERNO>/<PATH_INT>/
</VirtualHost>

Analizamos cada una de las directivas:

<VirtualHost *:<PUERTO_EXTERNO> >

Define un VirtualHost. En lugar de * se podría indicar una dirección IP para que solamente se acceda al sitio a través de la misma y separado por dos puntos se indica el PUERTO_INTERNO donde se recibe la petición desde Internet

ServerName <DOMINIO_EXTERNO>

Indica el dominio donde se recibe la petición desde Internet

ProxyRequests Off

Evita que Apache funcione como un servidor proxy que realice forwarding (forward proxy server)

ProxyPreserveHost Off

No se utiliza el host que se indica en la petición que ingresa. Podría ser necesario en caso de que el servicio web lo requiera para evaluarlo de alguna manera.

ProxyPass /<PATH_EXT>/ http://<DOMINIO_INTERNO>:<PUERTO_INTERNO>/<PATH_INT>/

Realiza el mapeo del dominio externo a una url interna. El primer parámetro es un path dentro del DOMINIO_EXTERNO y el segundo es la correspondiente URL interna a la cual se convertirá.

Tip: si el primer parámetro termina con /, el segundo también debe hacerlo para evitar posibles errores en las construcciones de urls.

Ejemplo:

ProxyPassReverse /<PATH_EXT>/ http://<DOMINIO_INTERNO>:<PUERTO_INTERNO>/<PATH_INT>/

Ajusta la url de manera similar a ProxyPass pero en las redirecciones HTTP, dentro de las cabeceras: Location, Content-Location y URI. Es necesario para que funcione correctamente el proxy reverso, de lo contrario las redirecciones HTTP podrían saltarlo.

Ejemplo:

<VirtualHost *:80>
  ServerName externo.servicio.com

  ProxyRequests Off
  ProxyPreserveHost Off
  ProxyPass / http://interno.servicio.com:666/
  ProxyPassReverse / http://interno.servicio.com:666/
</VirtualHost>

En este caso podemos ver que Apache actuará como un proxy reverso para que cuando se acceda a http//externo.servicio.com:80/ se redirija la petición a http://interno.servicio.com:666/

3. Reiniciar Apache y probar

Una vez reiniciado el servicio de Apache podemos probar acceder a desde Internet al dominio externo (y al puerto externo), a partir de un navegador por ejemplo. Mediante DNS la petición se dirige hacia nuestro router LAN, el cual a través de la redirección de puertos la envía al equipo con Apache actuando de proxy reverso. Éste hace la conversión al dominio y puertos internos. La petición llega al servicio web interno correspondiente, quien finalmente la responde. Entonces esta respuesta sigue el mismo camino (pero ahora al revés) hasta mostrar la respuesta en el navegador. Las acciones de redirección de puertos y DNS no aplican en este sentido, pero la respuesta pasa por los dispositivos sabiendo a dónde debe dirigirse.

Bloquear acceso a directorios mediante reglas de reescritura de Apache

Si nuestra aplicación web contiene directorios, dependiendo la configuración de Apache, el contenido de los mismos podría ser accedido conociendo la URL completa al archivo. Ya sabemos evitar que los buscadores indexen páginas de nuestro sitio y ahora vamos a ser un poco más estrictos, no permitiendo acceder a ciertos directorios por web mediante el módulo rewrite de Apache.

Activar el módulo rewrite y permitir htaccess en directorios del VirtualHost

  1. En la ubicación donde instalamos Apache, abrir con un editor de textos el archivo: conf\httpd.conf
  2. Descomentar la línea: LoadModule rewrite_module modules/mod_rewrite.so
  3. En el VirtualHost correspondiente, dentro de la etiqueta Directory establecer: AllowOverride All
  4. Reiniciar el servicio de apache

Proteger directorios

  1. En la ubicación donde se encuentran los directorios a proteger, crear un archivo .htaccess
  2. Abrir este archivo con un editor de textos e indicar en su contenido:
 Options -Indexes
 RewriteEngine on
 RewriteCond %{REQUEST_URI} ^.*/<DIRECTORY>/.*$
 RewriteRule .*$ <FORBIDDEN_URL>

donde DIRECTORY es el directorio que deseamos proteger para que no pueda ser accedido y FORBIDDEN_URL es una url a la cual redirigir cuando se intente acceder a este directorio por web. No hace falta decir que:

  • se pueden bloquear todos los directorios que deseemos, incluso especificando subdirectorios, agregando más líneas de RewriteCond debajo de la presentada
  • los directorios no especificados podrán ser accedidos.

Ejemplo: Suponiendo que tenemos un blog en http://myblogtest y no queremos que se permita el acceso a los archivos de log contenidos en http://myblogtest/archive/logs, creamos el archivo .htaccess en http://myblogtest:

 Options -Indexes
 RewriteEngine on
 RewriteCond %{REQUEST_URI} ^.*/archive/logs/.*$
 RewriteRule .*$ http://myblogtest/forbidden.html

De esta manera se podrá acceder a http://myblogtest/archive/file1.zip, pero cuando intentemos http://myblogtest/archive/logs/process1.log automáticamente redireccionará a http://myblogtest/forbidden.html

Alternativamente podemos querer indicar solamente los directorios a los cuales permitimos el acceso web. Entonces el contenido del .htaccess es el siguiente:

 Options -Indexes
 RewriteEngine on
 RewriteCond %{REQUEST_URI} !^.*/<DIRECTORY>/.*$
 RewriteRule .*$ <FORBIDDEN_URL>

donde DIRECTORY es el directorio al que permitimos el acceso y FORBIDDEN_URL es una url a la cual redirigir cuando se intente acceder por web a cualquier directorio que NO sea el indicado.

Solucionar error de child process al ejecutar scripts CGI con código Perl desde Apache

Es posible que cuando intentemos acceder mediante un navegador a un script CGI con código Perl servido por Apache, obtengamos un Internal Server Error (500) y al ver el log de errores correspondiente veamos las siguientes líneas:

[Mon Sep 01 19:26:36 2014] [error] [client 127.0.0.1] (OS 2)El sistema no puede encontrar el archivo especificado.  : couldn't create child process: 720002: script.cgi, referer: http://localhost
[Mon Sep 01 19:26:36 2014] [error] [client 127.0.0.1] (OS 2)El sistema no puede encontrar el archivo especificado.  : couldn't spawn child process: C:/www/script.cgi, referer: http://localhost

En inglés el mensaje es parecido:

[Mon Sep 01 19:26:36 2014] [error] [client 127.0.0.1] (OS 2)The system cannot find the file specified.  : couldn't create child process: 720002: script.cgi, referer: http://localhost
[Mon Sep 01 19:26:36 2014] [error] [client 127.0.0.1] (OS 2)The system cannot find the file specified.  : couldn't spawn child process: C:/www/script.cgi, referer: http://localhost

Para solucionarlo simplemente debemos:

  1. Abrir el script.cgi con un editor de textos
  2. Ver la ruta hacia perl en la primer línea (shebang)
  3. Verificar que el ejecutable de perl esté en esa ruta

Si no hay coincidencia, tenemos 2 alternativas:

  1. Copiar el ejecutable de perl a la ruta donde lo busca el script
    • Lo recomiendo cuando son muchos los scripts que apuntan a esa ruta en el shebang o cuando es la ruta más común “usr/bin/perl
  2. Cambiar la ruta en el script para que apunte al directorio donde está instalado perl
    • Lo recomiendo cuando sea un único script o cuando tenemos perl en el directorio más común “usr/bin

Solucionar error de la extensión curl de PHP en Windows

Supongamos que necesitamos invocar una url a partir de nuestro código PHP. Una forma de hacerlo es mediante la extensión curl. Es posible que en Windows al intentar activarla, no logremos hacer que funcione.

Si el código que la utiliza es similar a:

<?php
  $ch=curl_init();
  curl_setopt($ch,CURLOPT_URL,'http://localhost/');
  curl_exec($ch);
  curl_close($ch);
 ?>

obtendremos el error:

Fatal error: Call to undefined function curl_init()

 

Para solucionarlo debemos primero verificar en el archivo de configuración php.ini que:

  • el directorio de extensiones (extension_dir) sea el correcto
  • la línea extension=php_curl.dll esté descomentada (sin el ; inicial)

A continuación ubicamos el directorio donde está instalado PHP y de allí copiamos los archivos:

  • libeay32.dll
  • ssleay32.dll

al directorio bin dentro de la ubicación donde se encuentra instalado de Apache.

Para finalizar reiniciamos el servicio de Apache.

 

Podemos corroborar que la extensión fue activada exitosamente a través de la información de phpinfo(), mediante un script con el código:

<?php
  phpinfo();
?>

Si volvemos a probar el código del principio veremos que funciona correctamente.