使用haproxy

时间:2017-09-27 07:55:26

标签: config reverse-proxy haproxy

我无法使用在ubuntu 16上运行的haproxy 1.6.3来使用反向代理设置。 继承人我想要实现的目标:

  • 在我的主机上,我有一个在https://bar.com下运行的apache的web应用程序,它使用mod_rewrite进行路由
  • 各种内部服务器(机器1..n)通过vpn链接到主机,所有只暴露了一个http接口,在vpn适配器的端口8081上支持websocket
  • 我希望内部机器可以通过主机的子目录访问,例如。对于机器1我想通过https://bar.com/machine1访问其网页 - 内部流量为http,主机到访问者的流量由主机的ssl证书保护
  • 所有其他与/ machine1不匹配的流量不应受到影响,应该像以前一样由主机apache提供服务
  • 机器1..n的转发Web界面上的路径不是问题,因为它们能够通过以下配置中的头指令(Orig-Path和X-Script-Path)动态修改其路径
  • 主机上的
  • apache2配置为仅使用Listen 127.0.0.1侦听localhost,并且主站点的所有流量都由haproxy通过默认后端处理

下面是相关的配置:

  • 主站点的apache .htaccess(不包括相关的子目录)

    # Exclude machine1 subdirectory from rewrite
    RewriteRule ^(machine1)($|/) - [L]
    RewriteCond %{REQUEST_URI} !^/index\.php
    RewriteCond %{SCRIPT_FILENAME} !-f
    RewriteCond %{SCRIPT_FILENAME} !-d
    RewriteRule .* index.php [L]
    
  • haproxy setup

    frontend http-in
        bind <external-ip>:80
        mode tcp
        option tcplog
        acl machine1 path_beg /machine1
        use_backend machine1-backend if machine1
        default_backend default-backend-http
    
    frontend https-in
        bind <external-ip>:80
        mode tcp
        option tcplog
        default_backend default-backend-https
    
    backend machine1-backend
        reqrep ^([^\ :]*)\ /machine1/(.*)  \1\ /\2
        http-request set-header Orig-Path /machine1/
        http-request set-header X-Script-Path /machine1/
        http-request set-header Host bar.com
        option http-server-close  
        server m1 10.0.0.4:8081
    
    backend default-backend-https
        server main 127.0.0.1:443
        mode tcp
    
    backend default-backend-http
        server main 127.0.0.1
        mode tcp
    

我目前的问题:

  • 访问未加密的变体(http://bar.com/machine1有时服务于machine1的正确页面,但大部分时间,我从主机apache获得404 - 我想这可以通过选项http-server-close解决,但不是 - 有人能指出我在这里缺少的东西吗?我在极少数情况下验证了使用/ machine1正确扩展路径的有效响应 - 例如/machine1/css/main.css用于css包括 - 但即使在从machine1初始拉取成功后 - 脚本,图像和css的所有后续提取也会再次返回404

  • 我无法弄清楚如何正确设置ssl以使用haproxy处理https-&gt; http流量转换的/ machine1请求,因此ssl部分不包括路由时刻 - 我如何扩展配置以使其适用于https://bar.com/machine1? (假设在/etc/keys/web.pem下存在bar.com的有效证书)

奖金问题:

  • 有没有机会让这个配置动态化?例如从数据库中提取相关信息(服务器IP,子目录名称)/使用某种逻辑,因为机器1 ... n链接将在运行时更改(新机器连接,其他连接断开,可能的机器数量是非常大)
  • 在使用/ machine1之前是否有选项可以验证用户?主Web应用程序进行用户管理,因此我最好在允许访问/ machine1之前检查用户是否已经过身份验证 - 可以这样做吗?

1 个答案:

答案 0 :(得分:2)

在这里回答我自己的问题: 经过一些研究,在这个用例的配置中问题是错误的模式tcp,并且可以通过在前端和后端切换模式到http来轻松解决。 来自docs

  • mode tcp
  

在此模式下,HAProxy不会解密流量。它只是打开一个   客户端和服务器之间的TCP隧道让它们在一起   协商并处理TLS流量。

使用此模式时,HAProxy不会评估数据包中的HTTP标头。在这种情况下,一个人似乎没有选择区分像http这样的http特定标头的后端,这就是为什么初始配置不起作用。

  • mode http
  

在此模式下,HAProxy会破解客户端的流量   在服务器端重新加密它。它可以访问的内容   请求和响应并执行高级处理   流量。

在这种情况下,所有http头字段都可供haproxy用于后端选择。

这当然会对ssl产生影响 - 这个设置有各种变体,我选择使用SSL / TLS卸载,让HAProxy破译客户端的流量,并清楚地连接到内部服务器。

这使得运行haproxy的机器成为sslendpoint,并且需要在此处而不是在Web服务器上设置ssl证书。此外,通过此设置,运行webapp的Web服务器可以完全隔离,仅在haproxy机器内部提供页面。这也回答了问题2.

最后,对于奖金问题:

  • 我已经走上了一条充满活力的路线。配置通过shell脚本,当新机器与数据库中的信息连接时,动态修改haproxy配置,使更改与service haproxy reload(ubuntu)一起生效 - 这看起来效果很好。
  • 对于用户身份验证,我设置了后端计算机现在查询主Web应用程序以进行授权,并在授权被拒绝时重定向到主Web应用程序。为了验证,使用cookie(或不存在cookie)。我目前正在测试此设置,但现在它看起来会起作用。

最后,我得到的(工作)配置(请注意,我已经在haproxy上添加了http到https重定向):

frontend http-in
    bind <external-ip>:80
    bind <external-ip>:443 ssl crt /path/to/cert/cert.pem
    acl machine1 path_beg /machine1
    reqadd X-Forwarded-Proto:\ https
    mode http
    option httplog
    use_backend machine1-backend if machine1
    default_backend default-backend

backend default-backend
    redirect scheme https if !{ ssl_fc }
    server main 127.0.0.1:80
    mode http

backend machine1-backend
    http-request set-header Orig-Path /machine1/
    http-request set-header X-Script-Path /machine1/
    http-request set-header Host bar.com
    reqirep ^([^\ :]*)\ /machine1/(.*)  \1\ /\2
    server m1 10.0.0.4:8081