frp/pkg/util/vhost/https.go

84 lines
2.6 KiB
Go
Raw Normal View History

2016-06-13 16:19:24 +02:00
// Copyright 2016 fatedier, fatedier@gmail.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package vhost
import (
"crypto/tls"
2016-06-13 16:19:24 +02:00
"io"
2019-10-12 14:13:12 +02:00
"net"
2016-06-13 16:19:24 +02:00
"time"
2023-05-29 08:10:34 +02:00
libnet "github.com/fatedier/golib/net"
2016-06-13 16:19:24 +02:00
)
2020-05-24 11:48:37 +02:00
type HTTPSMuxer struct {
*Muxer
2016-06-13 16:19:24 +02:00
}
2020-05-24 11:48:37 +02:00
func NewHTTPSMuxer(listener net.Listener, timeout time.Duration) (*HTTPSMuxer, error) {
2023-03-07 12:53:32 +01:00
mux, err := NewMuxer(listener, GetHTTPSHostname, timeout)
if err != nil {
return nil, err
}
2020-05-24 11:48:37 +02:00
return &HTTPSMuxer{mux}, err
2016-06-13 16:19:24 +02:00
}
2020-05-24 11:48:37 +02:00
func GetHTTPSHostname(c net.Conn) (_ net.Conn, _ map[string]string, err error) {
reqInfoMap := make(map[string]string, 0)
2023-05-29 08:10:34 +02:00
sc, rd := libnet.NewSharedConn(c)
clientHello, err := readClientHello(rd)
2016-06-13 16:19:24 +02:00
if err != nil {
2018-05-08 18:23:42 +02:00
return nil, reqInfoMap, err
2016-06-13 16:19:24 +02:00
}
reqInfoMap["Host"] = clientHello.ServerName
reqInfoMap["Scheme"] = "https"
2019-10-12 14:13:12 +02:00
return sc, reqInfoMap, nil
2016-06-13 16:19:24 +02:00
}
func readClientHello(reader io.Reader) (*tls.ClientHelloInfo, error) {
var hello *tls.ClientHelloInfo
// Note that Handshake always fails because the readOnlyConn is not a real connection.
// As long as the Client Hello is successfully read, the failure should only happen after GetConfigForClient is called,
// so we only care about the error if hello was never set.
err := tls.Server(readOnlyConn{reader: reader}, &tls.Config{
GetConfigForClient: func(argHello *tls.ClientHelloInfo) (*tls.Config, error) {
hello = &tls.ClientHelloInfo{}
*hello = *argHello
return nil, nil
},
}).Handshake()
if hello == nil {
return nil, err
}
return hello, nil
}
type readOnlyConn struct {
reader io.Reader
}
func (conn readOnlyConn) Read(p []byte) (int, error) { return conn.reader.Read(p) }
func (conn readOnlyConn) Write(p []byte) (int, error) { return 0, io.ErrClosedPipe }
func (conn readOnlyConn) Close() error { return nil }
func (conn readOnlyConn) LocalAddr() net.Addr { return nil }
func (conn readOnlyConn) RemoteAddr() net.Addr { return nil }
func (conn readOnlyConn) SetDeadline(t time.Time) error { return nil }
func (conn readOnlyConn) SetReadDeadline(t time.Time) error { return nil }
func (conn readOnlyConn) SetWriteDeadline(t time.Time) error { return nil }