Skip to content

Commit b4d5d8c

Browse files
authored
plugin https2http&https2https: return 421 if host not match sni (#4323)
1 parent c6f9d8d commit b4d5d8c

File tree

6 files changed

+81
-13
lines changed

6 files changed

+81
-13
lines changed

Release.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
### Features
22

33
* Added a new plugin "http2http" which allows forwarding HTTP requests to another HTTP server, supporting options like local address binding, host header rewrite, and custom request headers.
4+
* Added `enableHTTP2` option to control whether to enable HTTP/2 in plugin https2http and https2https, default is true.
5+
6+
### Changes
7+
8+
* Plugin https2http & https2https: return 421 `Misdirected Request` if host not match sni.

pkg/config/v1/plugin.go

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,15 @@ import (
2020
"errors"
2121
"fmt"
2222
"reflect"
23+
24+
"github.com/samber/lo"
25+
26+
"github.com/fatedier/frp/pkg/util/util"
2327
)
2428

25-
type ClientPluginOptions interface{}
29+
type ClientPluginOptions interface {
30+
Complete()
31+
}
2632

2733
type TypedClientPluginOptions struct {
2834
Type string `json:"type"`
@@ -73,21 +79,21 @@ const (
7379
PluginHTTPProxy = "http_proxy"
7480
PluginHTTPS2HTTP = "https2http"
7581
PluginHTTPS2HTTPS = "https2https"
82+
PluginHTTP2HTTP = "http2http"
7683
PluginSocks5 = "socks5"
7784
PluginStaticFile = "static_file"
7885
PluginUnixDomainSocket = "unix_domain_socket"
79-
PluginHTTP2HTTP = "http2http"
8086
)
8187

8288
var clientPluginOptionsTypeMap = map[string]reflect.Type{
8389
PluginHTTP2HTTPS: reflect.TypeOf(HTTP2HTTPSPluginOptions{}),
8490
PluginHTTPProxy: reflect.TypeOf(HTTPProxyPluginOptions{}),
8591
PluginHTTPS2HTTP: reflect.TypeOf(HTTPS2HTTPPluginOptions{}),
8692
PluginHTTPS2HTTPS: reflect.TypeOf(HTTPS2HTTPSPluginOptions{}),
93+
PluginHTTP2HTTP: reflect.TypeOf(HTTP2HTTPPluginOptions{}),
8794
PluginSocks5: reflect.TypeOf(Socks5PluginOptions{}),
8895
PluginStaticFile: reflect.TypeOf(StaticFilePluginOptions{}),
8996
PluginUnixDomainSocket: reflect.TypeOf(UnixDomainSocketPluginOptions{}),
90-
PluginHTTP2HTTP: reflect.TypeOf(HTTP2HTTPPluginOptions{}),
9197
}
9298

9399
type HTTP2HTTPSPluginOptions struct {
@@ -97,36 +103,61 @@ type HTTP2HTTPSPluginOptions struct {
97103
RequestHeaders HeaderOperations `json:"requestHeaders,omitempty"`
98104
}
99105

106+
func (o *HTTP2HTTPSPluginOptions) Complete() {}
107+
100108
type HTTPProxyPluginOptions struct {
101109
Type string `json:"type,omitempty"`
102110
HTTPUser string `json:"httpUser,omitempty"`
103111
HTTPPassword string `json:"httpPassword,omitempty"`
104112
}
105113

114+
func (o *HTTPProxyPluginOptions) Complete() {}
115+
106116
type HTTPS2HTTPPluginOptions struct {
107117
Type string `json:"type,omitempty"`
108118
LocalAddr string `json:"localAddr,omitempty"`
109119
HostHeaderRewrite string `json:"hostHeaderRewrite,omitempty"`
110120
RequestHeaders HeaderOperations `json:"requestHeaders,omitempty"`
121+
EnableHTTP2 *bool `json:"enableHTTP2,omitempty"`
111122
CrtPath string `json:"crtPath,omitempty"`
112123
KeyPath string `json:"keyPath,omitempty"`
113124
}
114125

126+
func (o *HTTPS2HTTPPluginOptions) Complete() {
127+
o.EnableHTTP2 = util.EmptyOr(o.EnableHTTP2, lo.ToPtr(true))
128+
}
129+
115130
type HTTPS2HTTPSPluginOptions struct {
116131
Type string `json:"type,omitempty"`
117132
LocalAddr string `json:"localAddr,omitempty"`
118133
HostHeaderRewrite string `json:"hostHeaderRewrite,omitempty"`
119134
RequestHeaders HeaderOperations `json:"requestHeaders,omitempty"`
135+
EnableHTTP2 *bool `json:"enableHTTP2,omitempty"`
120136
CrtPath string `json:"crtPath,omitempty"`
121137
KeyPath string `json:"keyPath,omitempty"`
122138
}
123139

140+
func (o *HTTPS2HTTPSPluginOptions) Complete() {
141+
o.EnableHTTP2 = util.EmptyOr(o.EnableHTTP2, lo.ToPtr(true))
142+
}
143+
144+
type HTTP2HTTPPluginOptions struct {
145+
Type string `json:"type,omitempty"`
146+
LocalAddr string `json:"localAddr,omitempty"`
147+
HostHeaderRewrite string `json:"hostHeaderRewrite,omitempty"`
148+
RequestHeaders HeaderOperations `json:"requestHeaders,omitempty"`
149+
}
150+
151+
func (o *HTTP2HTTPPluginOptions) Complete() {}
152+
124153
type Socks5PluginOptions struct {
125154
Type string `json:"type,omitempty"`
126155
Username string `json:"username,omitempty"`
127156
Password string `json:"password,omitempty"`
128157
}
129158

159+
func (o *Socks5PluginOptions) Complete() {}
160+
130161
type StaticFilePluginOptions struct {
131162
Type string `json:"type,omitempty"`
132163
LocalPath string `json:"localPath,omitempty"`
@@ -135,15 +166,11 @@ type StaticFilePluginOptions struct {
135166
HTTPPassword string `json:"httpPassword,omitempty"`
136167
}
137168

169+
func (o *StaticFilePluginOptions) Complete() {}
170+
138171
type UnixDomainSocketPluginOptions struct {
139172
Type string `json:"type,omitempty"`
140173
UnixPath string `json:"unixPath,omitempty"`
141174
}
142175

143-
// Added HTTP2HTTPPluginOptions struct
144-
type HTTP2HTTPPluginOptions struct {
145-
Type string `json:"type,omitempty"`
146-
LocalAddr string `json:"localAddr,omitempty"`
147-
HostHeaderRewrite string `json:"hostHeaderRewrite,omitempty"`
148-
RequestHeaders HeaderOperations `json:"requestHeaders,omitempty"`
149-
}
176+
func (o *UnixDomainSocketPluginOptions) Complete() {}

pkg/config/v1/proxy.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ func (c *ProxyBaseConfig) Complete(namePrefix string) {
127127
c.Name = lo.Ternary(namePrefix == "", "", namePrefix+".") + c.Name
128128
c.LocalIP = util.EmptyOr(c.LocalIP, "127.0.0.1")
129129
c.Transport.BandwidthLimitMode = util.EmptyOr(c.Transport.BandwidthLimitMode, types.BandwidthLimitModeClient)
130+
131+
if c.Plugin.ClientPluginOptions != nil {
132+
c.Plugin.ClientPluginOptions.Complete()
133+
}
130134
}
131135

132136
func (c *ProxyBaseConfig) MarshalToMsg(m *msg.NewProxy) {

pkg/plugin/client/https2http.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ import (
2727
"time"
2828

2929
"github.com/fatedier/golib/pool"
30+
"github.com/samber/lo"
3031

3132
v1 "github.com/fatedier/frp/pkg/config/v1"
3233
"github.com/fatedier/frp/pkg/transport"
34+
httppkg "github.com/fatedier/frp/pkg/util/http"
3335
"github.com/fatedier/frp/pkg/util/log"
3436
netpkg "github.com/fatedier/frp/pkg/util/net"
3537
)
@@ -71,6 +73,17 @@ func NewHTTPS2HTTPPlugin(options v1.ClientPluginOptions) (Plugin, error) {
7173
BufferPool: pool.NewBuffer(32 * 1024),
7274
ErrorLog: stdlog.New(log.NewWriteLogger(log.WarnLevel, 2), "", 0),
7375
}
76+
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
77+
if r.TLS != nil {
78+
tlsServerName, _ := httppkg.CanonicalHost(r.TLS.ServerName)
79+
host, _ := httppkg.CanonicalHost(r.Host)
80+
if tlsServerName != "" && tlsServerName != host {
81+
w.WriteHeader(http.StatusMisdirectedRequest)
82+
return
83+
}
84+
}
85+
rp.ServeHTTP(w, r)
86+
})
7487

7588
var (
7689
tlsConfig *tls.Config
@@ -87,10 +100,13 @@ func NewHTTPS2HTTPPlugin(options v1.ClientPluginOptions) (Plugin, error) {
87100
}
88101

89102
p.s = &http.Server{
90-
Handler: rp,
103+
Handler: handler,
91104
ReadHeaderTimeout: 60 * time.Second,
92105
TLSConfig: tlsConfig,
93106
}
107+
if !lo.FromPtr(opts.EnableHTTP2) {
108+
p.s.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler))
109+
}
94110

95111
go func() {
96112
_ = p.s.ServeTLS(listener, "", "")

pkg/plugin/client/https2https.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ import (
2727
"time"
2828

2929
"github.com/fatedier/golib/pool"
30+
"github.com/samber/lo"
3031

3132
v1 "github.com/fatedier/frp/pkg/config/v1"
3233
"github.com/fatedier/frp/pkg/transport"
34+
httppkg "github.com/fatedier/frp/pkg/util/http"
3335
"github.com/fatedier/frp/pkg/util/log"
3436
netpkg "github.com/fatedier/frp/pkg/util/net"
3537
)
@@ -77,6 +79,17 @@ func NewHTTPS2HTTPSPlugin(options v1.ClientPluginOptions) (Plugin, error) {
7779
BufferPool: pool.NewBuffer(32 * 1024),
7880
ErrorLog: stdlog.New(log.NewWriteLogger(log.WarnLevel, 2), "", 0),
7981
}
82+
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
83+
if r.TLS != nil {
84+
tlsServerName, _ := httppkg.CanonicalHost(r.TLS.ServerName)
85+
host, _ := httppkg.CanonicalHost(r.Host)
86+
if tlsServerName != "" && tlsServerName != host {
87+
w.WriteHeader(http.StatusMisdirectedRequest)
88+
return
89+
}
90+
}
91+
rp.ServeHTTP(w, r)
92+
})
8093

8194
var (
8295
tlsConfig *tls.Config
@@ -93,10 +106,13 @@ func NewHTTPS2HTTPSPlugin(options v1.ClientPluginOptions) (Plugin, error) {
93106
}
94107

95108
p.s = &http.Server{
96-
Handler: rp,
109+
Handler: handler,
97110
ReadHeaderTimeout: 60 * time.Second,
98111
TLSConfig: tlsConfig,
99112
}
113+
if !lo.FromPtr(opts.EnableHTTP2) {
114+
p.s.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler))
115+
}
100116

101117
go func() {
102118
_ = p.s.ServeTLS(listener, "", "")

pkg/util/version/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
package version
1616

17-
var version = "0.58.1"
17+
var version = "0.59.0"
1818

1919
func Full() string {
2020
return version

0 commit comments

Comments
 (0)