Redirección de Haproxy según la ruta

Redirección de Haproxy según la ruta

Similar aHAProxy solicita eliminar URI en la solicitud de backend.

Las siguientes preocupaciones se aplican a nosotros.

Tenemos aplicaciones que se ejecutaban con diferentes raíces de contexto en un dominio. Sin embargo, no se cambiaron todos los clientes de las URL.

Me gustaría redirigir con una redirección 301 en haproxy si una solicitud coincide con una ruta heredada.

Tomemos por ejemplo http://example.com/abcyhttp://example.com/def

...
frontend https
  bind *:{{ proxy_port }} ssl crt /etc/haproxy/bundle_dh.pem ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4 no-sslv3
  http-request set-header X-Forwarded-Proto https if { ssl_fc }
  http-request set-header X-Forwarded-Port %[dst_port]

  acl has_legacy_abc path_beg /abc
  acl has_legacy_def path_beg /def
  redirect location 301 https://abcdomain.com/{PATH_WITHOUT_ABC} if { has_legacy_abc }
  redirect location 301 https://defdomain.com/{PATH_WITHOUT_ABC} if { has_legacy_def }

  use backend abc_backend if { hdr(Host) -i abcdomain.com }
  use backend def_backend if { hdr(Host) -i defdomain.com }
...

El problema es cómo conservar la ruta en la redirección. Puedo hacer una redirección absoluta.

Miré y reqrepeso parece ser para cambiar una solicitud antes de pasar a un backend. Quiero decirles a todos los visitantes que deberían ir al nuevo dominio.

Respuesta1

Esto se puede hacer usando algunos encabezados temporales como este, insertados entre sus acldefiniciones y use_backendpalabras clave:

http-request set-header X-Location-Path %[capture.req.uri] if has_legacy_abc OR has_legacy_def

http-request replace-header X-Location-Path [^/]+/(.*) \1 if has_legacy_abc OR has_legacy_def

http-request redirect location https://abcdomain.com/%[hdr(X-Location-Path)] if has_legacy_abc
http-request redirect location https://defdomain.com/%[hdr(X-Location-Path)] if has_legacy_def

Dependiendo de la configuración real de sus dominios/rutas y las redirecciones requeridas, incluso podría ser posible colapsarlo todo en un único conjunto de directivas, como esta:

...
frontend https
  bind *:{{ proxy_port }} ssl crt /etc/haproxy/bundle_dh.pem ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4 no-sslv3
  http-request set-header X-Forwarded-Proto https if { ssl_fc }
  http-request set-header X-Forwarded-Port %[dst_port]

  acl has_legacy path_beg /abc /def

  http-request set-header X-Location-Path %[capture.req.uri] if has_legacy
  http-request set-header X-Location-Host %[capture.req.uri] if has_legacy

  http-request replace-header X-Location-Host /([^/]*)/ \1 if has_legacy
  http-request replace-header X-Location-Path [^/]+/(.*) \1 if has_legacy

  http-request redirect location https://%[hdr(X-Location-Host)]domain.com/%[hdr(X-Location-Path)] if has_legacy_abc

  use backend abc_backend if { hdr(Host) -i abcdomain.com }
  use backend def_backend if { hdr(Host) -i defdomain.com }
...

Si el número de rutas y dominios es enorme, puede utilizarmapas(donde la clave es la ruta y el valor es el host de destino) para simplificar aún más las cosas.

Respuesta2

Tengo el mismo problema y encontré otra solución que creo que es mejor. Esta otra solución funciona bien con la versión 1.6+ de haproxy. Usasolicitud http y regsub.

Si reescribo tu ejemplo:

frontend https
  bind *:{{ proxy_port }} ssl crt /etc/haproxy/bundle_dh.pem ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4 no-sslv3
  acl has_legacy_abc path_beg /abc
  acl has_legacy_def path_beg /def
  http-request redirect code 301 location https://%[hdr(host)]%[url,regsub(^/abc,/newabc,)] if has_legacy_abc

información relacionada