обратный прокси-сервер с несколькими веб-серверами по указанному URI обработчика c без перезаписи всей полезной нагрузки - PullRequest
0 голосов
/ 19 марта 2020

Я пытался решить мою проблему и не нашел Go способа сделать это. У меня есть пара веб-серверов, обслуживающих различные приложения, и мы постарались сделать их доступными для пользователей через одну веб-страницу. Мы думали об использовании обратного прокси. Я пытался nginx и сам кодировать его с помощью Go.

user --> xxx.domain.name ------> /app1 -----> reverse proxy to app1 at its root uri /
                                 /app2 -----> reverse proxy to app2 at its root uri /
                                 /app3 -----> reverse proxy to app3 at its root uri /

Проблема, с которой мы сталкиваемся, заключается в том, что он всегда добавляет / app1 в вызов веб-сервера в серверной части, когда это необходимо. позвонить /.

И переписать все будет много работы, так как мы не владеем кодом для этого внутреннего веб-сервера, и кажется, что многие URI в приложении жестко закодированы.

Кто-нибудь уже пробовал это и нашел способ сделать это без переписывания?

с помощью следующего кода, я могу создать обратный прокси-сервер, который отвечает на root (" / "), используя другой порт. То, что я искал, - это сохранить один порт и использовать / app1, / ​​app2 для перенаправления, но без добавления / app1 или / app2 к запросу вышестоящего сервера.

(я знаю, что код может быть улучшено, чтобы не повторять разбор URL в основном, но я исправлю это, когда найду решение своей проблемы)

package main

import (
    "crypto/tls"
    "errors"
    "log"
    "net/http"
    "net/url"
    "sync"
    "time"

    "github.com/labstack/echo"
    "github.com/labstack/echo/middleware"
)

var (
    certLock = new(sync.RWMutex)
    cert     *tls.Certificate
)

func main() {
    waf1, err := url.Parse("https://10.0.0.11:443")
    if err != nil {
        log.Fatal(err)
    }

    targets1 := []*middleware.ProxyTarget{
        {
            URL: waf1,
        },
    }

    waf2, err := url.Parse("https://10.0.2.11:443")
    if err != nil {
        log.Fatal(err)
    }

    targets2 := []*middleware.ProxyTarget{
        {
            URL: waf2,
        },
    }

    go server(":6001", targets1)
    server(":6002", targets2)
}

func server(port string, targets1 []*middleware.ProxyTarget) {
    e := echo.New()
    e.HideBanner = true
    e.Debug = true
    e.Server.ReadTimeout = 10 * time.Second
    e.Server.WriteTimeout = 2 * time.Minute

    e.Use(middleware.Recover())
    //e.Use(middleware.Logger())

    e.TLSServer.TLSConfig = new(tls.Config)
    e.TLSServer.TLSConfig.MinVersion = tls.VersionTLS12
    e.TLSServer.TLSConfig.PreferServerCipherSuites = true
    e.TLSServer.TLSConfig.CipherSuites = []uint16{
        tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
        tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
        tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
        tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
        tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
        tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
        tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
        tls.TLS_RSA_WITH_AES_128_CBC_SHA,
        tls.TLS_RSA_WITH_AES_256_CBC_SHA,
    }

    c, err := tls.LoadX509KeyPair("tls_certificate.pem", "tls_private_key.pem")
    if err != nil {
        log.Fatalln(err.Error())
        return
    }
    certLock.Lock()
    cert = &c
    certLock.Unlock()

    // configure certificate load function and listen on https
    e.TLSServer.TLSConfig.GetCertificate = GetCertificate
    e.TLSServer.Addr = port

    var defaultTransport http.RoundTripper = &http.Transport{
        TLSClientConfig: &tls.Config{
            InsecureSkipVerify: true,
        },
    }

    e.Use(middleware.ProxyWithConfig(middleware.ProxyConfig{
        Balancer:  middleware.NewRoundRobinBalancer(targets1),
        Transport: defaultTransport,
    }))

    e.Logger.Fatal(e.StartServer(e.TLSServer))
}

// GetCertificate extract certificate form PEM
func GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
    certLock.RLock()
    defer certLock.RUnlock()

    if cert == nil {
        return nil, errors.New("No certificate configured")
    }

    return cert, nil
}
...