Host virtual Apache basado en * fuente * IP

9

¿Es posible configurar Apache para diferentes hosts virtuales en función de la IP de origen ? (es decir, la misma interfaz, el mismo nombre de host, pero dos hosts virtuales diferentes, con contenido diferente, según la IP de origen ).

La motivación para esto es que mi dirección IP pueda acceder al sitio correctamente, pero que todos los demás obtengan la página de espera. La solución convencional parece ser usar mod_rewrite para dirigir a los visitantes a una página separada dentro de la misma docroot, pero en su lugar me gustaría usar una docroot completamente diferente para la página de retención.

ithinkihaveacat
fuente
Por cierto, ¿por qué necesita esta lógica para usted en el servidor? Puede asignar el dominio a la IP de un servidor de prueba (o su propia computadora) solo para usted usando su archivo de hosts.
Dan Grossman
¿tiene varios nombres para manejar o solo uno? como puedes trabajar (define los Virtualhosts) con nombres o con IP.
regilero
¿Alguna razón particular por la que una raíz de documento diferente?
anthonysomerset
El razonamiento declarado del OP no tiene sentido (una página de retención funciona muy bien con una reescritura), pero si usted estaba, por ejemplo, reelaborando un sitio, necesitaba una forma de alojar el retrabajo y no sabía que existían subdominios, podría decide hacerlo de esta manera.
womble
Puede usar las líneas Permitir / Denegar para bloquear el acceso a todos excepto a usted y tener un documento de error personalizado para errores 403 (Asegúrese de ponerlo en un directorio y permitir el acceso a ese directorio, de lo contrario el documento de error también será 403), o use las reglas de reescritura / las condiciones de reescritura, o mueva su sitio de prelanzamiento / prueba a un subdominio como dev.example.com y luego example.com podría tener la página de retención
Smudge

Respuestas:

5

No sé si eso es posible (sin mod_rewrite, de todos modos) en el nivel de Apache.

Aquí hay otra idea. ¿Qué sucede si configura dos hosts virtuales Apache y luego usa iptables para reenviar de forma transparente al visitante para corregir el host virtual? Algo como

iptables -A PREROUTING -t nat -i eth0 -p tcp -s your.ip.address -d your.server --dport 80 -j DNAT --to-destination your.actual.site:someport
iptables -A PREROUTING -t nat -i eth0 -p tcp ! -s your.ip.address -d your.server --dport 80 -j DNAT --to-destination your.holding.site:someport

O algo similar. :)

Janne Pikkarainen
fuente
Yo diría que esta será la peor opción.
womble
8

Realmente no sería un host virtual diferente. Pero usando algo como mod_rewrite o mod_alias puede servir contenido de cualquier carpeta para la que haya establecido los permisos apropiados. Solo hay un docroot, pero puedes cambiarlo efectivamente sobre la marcha.

Una forma de hacerlo podría ser:

<VirtualHost *.80>
    ServerName example.com
    ...
    DocumentRoot "/path/to/root"
    <Directory "/path/to/root">
       ...
    </Directory>
    <Directory "/path/to/not/root">
       Order allow,deny
       #replace with your IP
       Allow from 192.168.0.100 
       ...
    </Directory>
    RewriteEngine On
    #Rewrite to alternate path if IP address matches
    RewriteCond %{REMOTE_ADDR} ^192\.168\.0\.100$
    RewriteRule ^/(.*)$ /path/to/not/root/$1
<VirtualHost>

Sin embargo, tenga en cuenta que probablemente sería un poco más limpio manejar esto con un subdominio de desarrollo.

Mateo
fuente
4

Apache 2.3 o posterior

Con Apache 2.3 o posterior, aparentemente puede hacer algo como esto (probado):

<VirtualHost *:80>
    ServerName www.example.com

    <If "-R '10.10.10.10'">
        # The next version of the website...
        Alias /favicon.ico /home/ubuntu/website-new/favicon.ico
        Alias /static/ /home/ubuntu/static/
        WSGIScriptAlias / /home/ubuntu/website-new/main/wsgi.py
    </If>
    <Else>
        # The standard version (e.g. holding page).
        Alias /favicon.ico /home/ubuntu/website/favicon.ico
        Alias /static/ /home/ubuntu/static/
        WSGIScriptAlias / /home/ubuntu/website/main/wsgi.py
    </Else>

    # and so on...

</VirtualHost>

Apache 2.2 o anterior

Actualización: esta no es una buena solución. Vea abajo.

Tienes que hacer un truco como este. Tenga en cuenta lo [PT]que significa "paso a través". Sin él, se envía una redirección HTTP real al cliente, lo que probablemente no sea lo que desea. La [OR]cosa (que significa "o") muestra cómo hacer coincidir múltiples direcciones.

Alias /next/favicon.ico /home/ubuntu/website-new/favicon.ico
Alias /next/static/ /home/ubuntu/static/
WSGIScriptAlias /next /home/ubuntu/website-new/main/wsgi.py

Alias /favicon.ico /home/ubuntu/website/favicon.ico
Alias /static/ /home/ubuntu/static/
WSGIScriptAlias / /home/ubuntu/website/main/wsgi.py

# Rewrite for our IP.
RewriteEngine On
RewriteCond %{REMOTE_ADDR} ^80\.4\.170\.209$ [OR]
RewriteCond %{REMOTE_ADDR} ^94\.193\.52\.157$
RewriteRule ^/(.*) /next/$1 [PT]

Debe habilitar mod_rewritelo que puede hacer en Debian / Ubuntu con este comando:

sudo a2enmod rewrite

Tenga en cuenta que este método no prohíbe completamente que otras personas accedan a su sitio de prueba, por lo que probablemente desee agregar algo de seguridad, o simplemente elegir un prefijo más oscuro que next.

Actualización sobre el método mod_rewrite.

Hay un par de problemas con este método. Primero, Django no funciona con dos sitios en el mismo proceso como este, debe seguir las instrucciones en esta respuesta .

En segundo lugar, mod_rewrite no funciona con POSTsolicitudes . Todos los correos POSTelectrónicos se cambian silenciosamente GETy los datos de publicación se descartan. ¡Muy frustrante! Por lo tanto, te recomiendo que uses el ...

versión de iptables

Simplemente ejecute los servidores en dos puertos diferentes. Este incluye las cosas de WSGI para tener dos sitios de django separados.

<VirtualHost *:80>
    ServerName www.example.com

    Alias /favicon.ico /home/ubuntu/alpha/favicon.ico
    Alias /static/ /home/ubuntu/alpha/static/

    WSGIDaemonProcess alpha_wsgi user=www-data group=www-data
    WSGIScriptAlias / /home/ubuntu/alpha/alpha/wsgi.py
    WSGIProcessGroup alpha_wsgi

    ServerAdmin [email protected]

    ErrorLog ${APACHE_LOG_DIR}/error.log

    # Possible values include: debug, info, notice, warn, error, crit, alert, emerg.
    LogLevel warn

    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<VirtualHost *:1222>
    ServerName www.example.com

    Alias /favicon.ico /home/ubuntu/main/favicon.ico
    Alias /static/ /home/ubuntu/main/static/

    WSGIDaemonProcess main_wsgi user=www-data group=www-data
    WSGIScriptAlias / /home/ubuntu/main/main/wsgi.py
    WSGIProcessGroup main_wsgi

    ServerAdmin [email protected]

    ErrorLog ${APACHE_LOG_DIR}/error.log

    # Possible values include: debug, info, notice, warn, error, crit, alert, emerg.
    LogLevel warn

    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Luego puede usar este iptablescomando para enrutar solicitudes desde su dirección IP en el puerto 80 al puerto 1222:

sudo iptables -A PREROUTING -t nat -p tcp -s your.ip.address --dport 80 -j DNAT --to-destination :1222

Cambie -Aa -Dpara eliminar la regla.

Tenga en cuenta que los documentos sugieren que necesita agregar comandos Listeny adicionales NameVirtualHost, pero en realidad descubrí que funciona sin ellos, y agregarlos hizo que se rompiera (al menos en ubuntu).

Timmmm
fuente
¿Su respuesta para 2.3+ da Alias cannot occur within <Directory/Location/Files> sectionalguna solución? Realmente necesito esto: $
Gizmo
2

AFAIK, la única manera de hacer esto es vincular una ubicación dentro de la raíz del documento a su contenido fuera de la raíz del documento, luego reescribir la solicitud para eso.

Dan Grossman
fuente
1

Como dijo @Timmmm, pero corrigiendo la instrucción ipmatch (tenga en cuenta el '10 .10.10.10 '): ServerName www.example.com

<If "%{REMOTE_ADDR} -ipmatch '10.10.10.10'">
    # The next version of the website...
    Alias /favicon.ico /home/ubuntu/website-new/favicon.ico
    Alias /static/ /home/ubuntu/static/
    WSGIScriptAlias / /home/ubuntu/website-new/main/wsgi.py
</If>
<Else>
    # The standard version (e.g. holding page).
    Alias /favicon.ico /home/ubuntu/website/favicon.ico
    Alias /static/ /home/ubuntu/static/
    WSGIScriptAlias / /home/ubuntu/website/main/wsgi.py
</Else>

# and so on...

Porque de lo contrario, mostrará el error:

Cannot parse condition clause: -ipmatch requires subnet/netmask as constant argument
olivervbk
fuente