Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ssl Golang ReverseProxy带有Apache2 SNI/主机名错误_Ssl_Go_Apache2_Reverse Proxy_Sni - Fatal编程技术网

Ssl Golang ReverseProxy带有Apache2 SNI/主机名错误

Ssl Golang ReverseProxy带有Apache2 SNI/主机名错误,ssl,go,apache2,reverse-proxy,sni,Ssl,Go,Apache2,Reverse Proxy,Sni,我正在用Go编写自己的ReverseProxy。ReverseProxy应该连接我的Go Web服务器和我的apache2 Web服务器。但是,当我在另一个IP地址上运行reverseproxy时,我的Apache2 Web服务器在apache日志文件中出现以下错误:reverseproxy将请求发送到apache "Hosname xxxx provided via sni and hostname xxxx2 provided via http are different" 我的反向代理和

我正在用Go编写自己的ReverseProxy。ReverseProxy应该连接我的Go Web服务器和我的apache2 Web服务器。但是,当我在另一个IP地址上运行reverseproxy时,我的Apache2 Web服务器在apache日志文件中出现以下错误:reverseproxy将请求发送到apache

"Hosname xxxx provided via sni and hostname xxxx2 provided via http are different"
我的反向代理和apache Web服务器在https上运行

下面是一些代码:

func (p *Proxy) directorApache(req *http.Request) {
    mainServer := fmt.Sprintf("%s:%d", Config.HostMain, Config.PortMain)
    req.URL.Scheme = "https"
    req.URL.Host = mainServer
}

func (p *Proxy) directorGo(req *http.Request) {
    goServer := fmt.Sprintf("%s:%d", Config.GoHost, Config.GoPort)
    req.URL.Scheme = "http"
    req.URL.Host = goServer
}


func (p *Proxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
    fmt.Println(req.URL.Path)
    if p.isGoRequest(req) {
        fmt.Println("GO")
        p.goProxy.ServeHTTP(rw, req)
        return
    }
    p.httpProxy.ServeHTTP(rw, req)
}
func main() {

    var configPath = flag.String("conf", "./configReverse.json", "Path to the Json config file.")

    flag.Parse()
    proxy := New(*configPath)
    cert, err := tls.LoadX509KeyPair(Config.PathCert, Config.PathPrivateKey)
    if err != nil {
        log.Fatalf("server: loadkeys: %s", err)
    }
    config := tls.Config{InsecureSkipVerify: true, Certificates: []tls.Certificate{cert}}

    listener, err := net.Listen("tcp",
    net.JoinHostPort(proxy.Host, strconv.Itoa(proxy.Port)))
    if err != nil {
        log.Fatalf("server: listen: %s", err)
    }
    log.Printf("server: listening on %s")
    proxy.listener = tls.NewListener(listener, &config)

    serverHTTPS := &http.Server{
        Handler:   proxy.mux,
        TLSConfig: &config,
    }

    if err := serverHTTPS.Serve(proxy.listener); err != nil {
        log.Fatal("SERVER ERROR:", err)
    }
}
也许有人对这个问题有想法。

举个简单的例子 假设您正在启动对
https://your-proxy.local
。您的请求处理程序接受
http.request
struct并将其
URL
字段重写为
https://your-apache-backend.local

您没有考虑的是,原始HTTP请求还包含一个
Host
头(
Host:your proxy.local
)。将相同的请求传递给
http://your-apache-backend.local
,该请求中的
Host
标题仍然显示
Host:your proxy.local
。这就是Apache所抱怨的

解释 当您使用带有服务器名称指示(SNI)的TLS时,请求主机名不仅将用于DNS解析,还将用于选择用于建立TLS连接的SSL证书。另一方面,HTTP 1.1
Host
头用于Apache区分多个虚拟主机。两个名称必须匹配。以下文件中也提到了这一问题:

SNI/请求主机名不匹配,或者SNI提供主机名而请求不提供。

这是一个浏览器错误。Apache将以400类型错误拒绝该请求

解决方案 同时重写主机标题。如果要保留原始的
Host
头,可以将其存储在
X-Forwarded-Host
头中(这是一个非标准头,但在反向代理中广泛使用):

简短的例子 假设您正在启动对
https://your-proxy.local
。您的请求处理程序接受
http.request
struct并将其
URL
字段重写为
https://your-apache-backend.local

您没有考虑的是,原始HTTP请求还包含一个
Host
头(
Host:your proxy.local
)。将相同的请求传递给
http://your-apache-backend.local
,该请求中的
Host
标题仍然显示
Host:your proxy.local
。这就是Apache所抱怨的

解释 当您使用带有服务器名称指示(SNI)的TLS时,请求主机名不仅将用于DNS解析,还将用于选择用于建立TLS连接的SSL证书。另一方面,HTTP 1.1
Host
头用于Apache区分多个虚拟主机。两个名称必须匹配。以下文件中也提到了这一问题:

SNI/请求主机名不匹配,或者SNI提供主机名而请求不提供。

这是一个浏览器错误。Apache将以400类型错误拒绝该请求

解决方案 同时重写主机标题。如果要保留原始的
Host
头,可以将其存储在
X-Forwarded-Host
头中(这是一个非标准头,但在反向代理中广泛使用):


感谢您的好主意和解决方案。你说得对,我没想过。但我有一个问题。首先,我的req.Header根本没有主机字段。我手动添加了x转发主机。但是仅仅设置主机头并不能解决这个问题,我也遇到了同样的错误。所以我尝试直接设置req.Host。然后Apache错误被解决了,但是我的站点没有加载任何其他内容,我认为我在Apache上的php出现了一个错误。我认为请求有问题,因为我更换了主机?所以我认为它解决了问题。但是您必须使用req.Host=mainServer,因为请求头不会被使用,您认为它属于这个问题:think与此有关:我在之前的评论中提到的问题是我的AngularJS,因为不安全的Resource加载,因为我的reverseproxy运行在与我的AngularJS不同的ip上。在赫尔姆伯特向你开火。你让我高兴:)很乐意帮忙。我还更新了我的答案,以反映
req.Host=mainServer
的更改。我想我还有另一个问题,当我更改req.Host时,我在ReverseProxy上没有收到任何新的请求。也许是因为主机发送的响应或新请求是错误的?我现在不知道。我的意思是apache问题已经解决了,但现在我的reverseProxy无法正常工作。他从apache为我的网站提供服务,但当用户对其进行操作时,他没有收到新的请求。如果是另一个问题,可能值得一个新问题。也许也会帮助你。谢谢你的好主意和解决方案。你说得对,我没想过。但我有一个问题。首先,我的req.Header根本没有主机字段。我手动添加了x转发主机。但是仅仅设置主机头并不能解决这个问题,我也遇到了同样的错误。所以我尝试直接设置req.Host。然后Apache错误被解决了,但是我的站点没有加载任何其他内容,我认为我在Apache上的php出现了一个错误。我认为请求有问题,因为我更换了主机?所以我认为它解决了问题。但是您必须使用req.Host=mainServer,因为请求头不会被使用,您认为它属于这个问题:think与此有关:我在之前的评论中提到的问题是我的AngularJS,因为不安全的Resource加载,因为我的reverseproxy运行在与我的AngularJS不同的ip上。在赫尔姆伯特向你开火。你让我高兴:)很乐意帮忙。我还更新了我的答案,以反映
req.Host=mainServer
的更改。我想我还有另一个问题,我没有收到任何新的req
func (p *Proxy) directorApache(req *http.Request) {
    mainServer := fmt.Sprintf("%s:%d", Config.HostMain, Config.PortMain)
    req.URL.Scheme = "https"
    req.URL.Host = mainServer
    req.Header.Set("X-Forwarded-Host", req.Header().Get("Host"))
    req.Host = mainServer
}