equivalente de iptables para mac os x

56

Quiero reenviar solicitudes de 192.168.99.100:80a 127.0.0.1:8000. Así es como lo haría en Linux usando iptables:

iptables -t nat -A OUTPUT -p tcp --dport 80 -d 192.168.99.100 -j DNAT --to-destination 127.0.0.1:8000

¿Cómo hago lo mismo en MacOS X? Probé una combinación de ipfwcomandos sin mucho éxito:

ipfw add fwd 127.0.0.1,8000 tcp from any to 192.168.99.100 80

(El éxito para mí es apuntar un navegador http://192.168.99.100y obtener una respuesta de un servidor de desarrollo en el que me estoy ejecutando localhost:8000)

nafe
fuente
¿Estamos hablando de cliente o servidor OSX?
Scott Pack
1
Es leopardo de las nieves.
nafe
¿Hay alguna razón por la que no pueda simplemente configurar su servidor web para que también escuche en 192.168.99.100:80?
Zoredache
1
@Zoredache Escuchar en el puerto 80 necesita sudo y algunos servidores web no pierden privilegios lo suficientemente rápido como para ejecutarlos de manera segura con sudo.
Navin

Respuestas:

33

Entonces descubrí una manera de hacer esto. No estoy seguro de si es la forma preferida, ¡pero funciona! En tu caparazón favorito:

sudo ifconfig lo0 10.0.0.1 alias
sudo ipfw add fwd 127.0.0.1,9090 tcp from me to 10.0.0.1 dst-port 80

(El alias lo0parece ser la parte que falta)

Si desea que un dominio (falso) apunte a este nuevo alias, asegúrese de que / etc / hosts contenga la línea:

10.0.0.1 www.your-domain.com
nafe
fuente
44
ipfw no funcionará en Yosemite (MAC) y parece un poco obsoleto
Vadorequest
25

Pude hacer que esto funcionara usando los comandos ifconfigy pfctlen Mac 10.10.2. Con el siguiente enfoque, estoy mapeando 127.0.0.1:3000con éxito mydomain.comlocalmente en mi máquina.

En su línea de comando ingrese los siguientes dos comandos para reenviar conexiones 127.0.0.1:3000a 10.0.0.1:

sudo ifconfig lo0 10.0.0.1 alias
echo "rdr pass on lo0 inet proto tcp from any to 10.0.0.1 port 80 -> 127.0.0.1 port 3000" | sudo pfctl -ef -

Luego edite su archivo /etc/hostso /private/etc/hostsy agregue la siguiente línea para asignar su dominio 10.0.0.1.

10.0.0.1 mydomain.com

Después de guardar su archivo de hosts, vacíe su DNS local:

sudo discoveryutil udnsflushcaches

Ahora ábralo mydomain.comen un navegador y verá el servidor alojado en su puerto localhost (es decir 127.0.0.1:3000). Básicamente, este proceso asigna un <ip>:<port>nuevo a un nuevo <ip>para que luego pueda asignar un host que IP.

Kevin Leary
fuente
1
Solo un poco hacky, pero hace el trabajo. Buen espectaculo.
Joey Carson
66
Gracias. ¿Cómo deshacerías el alias y el reenvío?
Carlos Nuñez
1
Hola sudo discoveryutil udnsflushcachesme da command not foundpero aún coincide con la entrada correctamente. Pero, ¿cómo puedo mapear un segundo puerto? Intenté hacer los pasos 1 + 2 con id: 10.0.0.2y otro puerto, pero siempre toma solo la última conexión. Entonces, si lo hago último 10.0.0.1y port 3000hacia adelante 3000, si lo hago 10.0.0.2y lo porto 4000hacia adelante 4000. En mi /private/etc/hostsescribí ambas entradas con la (diferente) identificación.
Andi Giga
Funciona, pero lo necesito nuevamente cuando reinicio OSX ... ¿Hay algo para guardar esto permanentemente?
Kasper
1
sudo dscacheutil -flushcache
Actualice
5

Yo también tuve que hacer algo similar recientemente, y al buscar encontré esta respuesta. Desafortunadamente, la respuesta de Nafe utiliza ipfwque ahora está en desuso y no está disponible en OSX; y la respuesta de Kevin Leary es de hecho un poco dura. Así que tuve que hacer algo mejor (más limpio) y decidí compartirlo aquí para la posteridad. Esta respuesta se basa en gran medida en el enfoque mencionado en esta esencia .

Como OP menciona, apuntar un navegador a 192.168.99.100 debería obtener una respuesta de un servidor en localhost: 8000. Agregar un alias ifconfigno es realmente necesario, pfctlsolo es suficiente: para lograr esto, el pf.confarchivo /etc/pf.confdebe modificarse.

Primero creamos (con sudo) un nuevo archivo de anclaje (llamémosle redirection) en: /etc/pf.anchors/redirection. Esto es básicamente un archivo de texto normal y contiene la siguiente línea (al igual que en la respuesta de Kevin Leary): rdr pass on lo0 inet proto tcp from any to 192.168.99.100 port = 80 -> 127.0.0.1 port 8000. Una vez que se ha creado el nuevo archivo de anclaje, debe ser referenciado dentro del pf.confarchivo. Abra el pf.confarchivo con sudo y agregue rdr-anchor "redirection"después de la última línea rdr-anchor (que es rdr-anchor "com.apple/*") y agregue load anchor "redirection" from "/etc/pf.anchors/redirection"al final.

En última instancia, así es como debería verse el archivo pf.conf:

scrub-anchor "com.apple/*"
nat-anchor "com.apple/*"
rdr-anchor "com.apple/*"
rdr-anchor "redirection"  #added for redirection/port forwarding
dummynet-anchor "com.apple/*"
anchor "com.apple/*"
load anchor "com.apple" from "/etc/pf.anchors/com.apple"
load anchor "pow" from "/etc/pf.anchors/redirection"  #added for redirection/port forwarding

Y eso es casi todo. Simplemente reinicie pfctlemitiendo sudo pfctl -dpara deshabilitarlo primero y luego sudo pfctl -fe /etc/pf.confpara iniciarlo nuevamente.

Ahora, si necesita que esto suceda automáticamente después de cada reinicio, debe realizarse otro pequeño trabajo: el daemon de lanzamiento pfctldebe actualizarse (la esencia mencionada menciona que pf se habilita automáticamente en el arranque, sin embargo, esto no parece ser el caso de mirar el código). Abra (con sudo) System/Library/LaunchDaemons/com.apple.pfctl.plisty busque esto:

<array>
          <string>pfctl</string>
          <string>-f</string>
          <string>/etc/pf.conf</string>
</array>

y agregue la línea <string>-e</string>para finalmente hacerlo así:

<array>
         <string>pfctl</string>
         <string>-e</string>
         <string>-f</string>
         <string>/etc/pf.conf</string>
</array>

Deberias hacer eso.

Advertencia : Apple ya no permite cambiar los archivos de demonio de lanzamiento así (no con sudo, ni chmod, ni nada más). La única forma es jugar con la configuración de Protección de integridad del sistema : iniciar en modo de recuperación y ejecutar terminal. Verifique el estado de SIP con csrutil status, generalmente debería estar habilitado. Deshabilítelo csrutil disabley reinicie en modo normal y luego realice los cambios en el archivo plist como se discutió anteriormente. Una vez hecho esto, regrese al modo de recuperación y vuelva a habilitar la protección (está en su lugar por una buena razón) mediante la emisión csrutil enable.

Explicación: Se puede verificar emitiendo el ifconfigcomando que 127.0.0.1ya es el alias (predeterminado) para localhost lo0; este hecho se está utilizando para evitar tener que agregar un alias adicional para localhost y simplemente usar la dirección predeterminada en el pf.confarchivo.

ACTUALIZACIÓN: Desafortunadamente, parece que cargar el archivo al inicio no funciona. Todavía estoy tratando de obtener ayuda para solucionarlo. Hasta entonces, correr sudo pfctl -f /etc/pf.confdespués de arrancar hace el truco.

Yogesch
fuente
Gracias por esto, esto funcionó para mí en OS X Sierra. Sin embargo, es muy importante que el archivo de redirección termine con una nueva línea.
kadrian
No parece seguro sobrescribir archivos del sistema como System/Library/LaunchDaemons/com.apple.pfctl.plist; esto probablemente no sobreviviría a una actualización del sistema operativo?
Tom
1

A partir de la 10.5, OS X viene con un nuevo firewall orientado a aplicaciones en lugar de ipfw. Pero ipfw todavía está instalado. Si tiene problemas con su sintaxis, consulte las interfaces gráficas como WaterRoofo Flying Buttress.

HTH, PEra

PEra
fuente
1

el orden de las reglas es importante, asegúrese de que no haya "negar todo" antes de permitir las reglas, o algo así.

monomito
fuente
Gracias por el consejo, pero no creo que tenga ese problema en particular (la lista ipfw solo muestra mi regla y 65535 allow ip from any to any).
nafe
1

Parece que a su comando le falta un número de regla; tratar:

ipfw add 100 fwd 127.0.0.1,8000 tcp from any to 192.168.99.100 80

(si no se está ejecutando como root, deberá agregarle el prefijo sudo). Otra cosa para verificar es que el firewall está habilitado:

sysctl net.inet.ip.fw.enable

Si vuelve con el valor 0 (apagado), enciéndalo con:

sysctl -w sysctl net.inet.ip.fw.enable=1

... y luego haga arreglos para que se vuelva a habilitar cuando la computadora se reinicie. La forma "adecuada" de hacer esto es probablemente crear un elemento lanzado ( Lingon lo hace bastante fácil). O simplemente use una de las herramientas GUI mencionadas por PEra, y deje que se encargue de los detalles.

Gordon Davisson
fuente