forked from Mxmilu666/frp
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
e66f45d8be
|
|||
|
cc0b8d0f94
|
|||
|
27237542c8
|
@@ -370,6 +370,15 @@ localAddr = "127.0.0.1:443"
|
|||||||
hostHeaderRewrite = "127.0.0.1"
|
hostHeaderRewrite = "127.0.0.1"
|
||||||
requestHeaders.set.x-from-where = "frp"
|
requestHeaders.set.x-from-where = "frp"
|
||||||
|
|
||||||
|
[[proxies]]
|
||||||
|
name = "plugin_http2https_redirect"
|
||||||
|
type = "http"
|
||||||
|
customDomains = ["test.yourdomain.com"]
|
||||||
|
[proxies.plugin]
|
||||||
|
type = "http2https_redirect"
|
||||||
|
# Optional. Defaults to 443. Set this if the HTTPS entry is exposed on a non-standard port.
|
||||||
|
# httpsPort = 443
|
||||||
|
|
||||||
[[proxies]]
|
[[proxies]]
|
||||||
name = "plugin_http2http"
|
name = "plugin_http2http"
|
||||||
type = "tcp"
|
type = "tcp"
|
||||||
|
|||||||
@@ -27,29 +27,31 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PluginHTTP2HTTPS = "http2https"
|
PluginHTTP2HTTPS = "http2https"
|
||||||
PluginHTTPProxy = "http_proxy"
|
PluginHTTP2HTTPSRedirect = "http2https_redirect"
|
||||||
PluginHTTPS2HTTP = "https2http"
|
PluginHTTPProxy = "http_proxy"
|
||||||
PluginHTTPS2HTTPS = "https2https"
|
PluginHTTPS2HTTP = "https2http"
|
||||||
PluginHTTP2HTTP = "http2http"
|
PluginHTTPS2HTTPS = "https2https"
|
||||||
PluginSocks5 = "socks5"
|
PluginHTTP2HTTP = "http2http"
|
||||||
PluginStaticFile = "static_file"
|
PluginSocks5 = "socks5"
|
||||||
PluginUnixDomainSocket = "unix_domain_socket"
|
PluginStaticFile = "static_file"
|
||||||
PluginTLS2Raw = "tls2raw"
|
PluginUnixDomainSocket = "unix_domain_socket"
|
||||||
PluginVirtualNet = "virtual_net"
|
PluginTLS2Raw = "tls2raw"
|
||||||
|
PluginVirtualNet = "virtual_net"
|
||||||
)
|
)
|
||||||
|
|
||||||
var clientPluginOptionsTypeMap = map[string]reflect.Type{
|
var clientPluginOptionsTypeMap = map[string]reflect.Type{
|
||||||
PluginHTTP2HTTPS: reflect.TypeOf(HTTP2HTTPSPluginOptions{}),
|
PluginHTTP2HTTPS: reflect.TypeOf(HTTP2HTTPSPluginOptions{}),
|
||||||
PluginHTTPProxy: reflect.TypeOf(HTTPProxyPluginOptions{}),
|
PluginHTTP2HTTPSRedirect: reflect.TypeOf(HTTP2HTTPSRedirectPluginOptions{}),
|
||||||
PluginHTTPS2HTTP: reflect.TypeOf(HTTPS2HTTPPluginOptions{}),
|
PluginHTTPProxy: reflect.TypeOf(HTTPProxyPluginOptions{}),
|
||||||
PluginHTTPS2HTTPS: reflect.TypeOf(HTTPS2HTTPSPluginOptions{}),
|
PluginHTTPS2HTTP: reflect.TypeOf(HTTPS2HTTPPluginOptions{}),
|
||||||
PluginHTTP2HTTP: reflect.TypeOf(HTTP2HTTPPluginOptions{}),
|
PluginHTTPS2HTTPS: reflect.TypeOf(HTTPS2HTTPSPluginOptions{}),
|
||||||
PluginSocks5: reflect.TypeOf(Socks5PluginOptions{}),
|
PluginHTTP2HTTP: reflect.TypeOf(HTTP2HTTPPluginOptions{}),
|
||||||
PluginStaticFile: reflect.TypeOf(StaticFilePluginOptions{}),
|
PluginSocks5: reflect.TypeOf(Socks5PluginOptions{}),
|
||||||
PluginUnixDomainSocket: reflect.TypeOf(UnixDomainSocketPluginOptions{}),
|
PluginStaticFile: reflect.TypeOf(StaticFilePluginOptions{}),
|
||||||
PluginTLS2Raw: reflect.TypeOf(TLS2RawPluginOptions{}),
|
PluginUnixDomainSocket: reflect.TypeOf(UnixDomainSocketPluginOptions{}),
|
||||||
PluginVirtualNet: reflect.TypeOf(VirtualNetPluginOptions{}),
|
PluginTLS2Raw: reflect.TypeOf(TLS2RawPluginOptions{}),
|
||||||
|
PluginVirtualNet: reflect.TypeOf(VirtualNetPluginOptions{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientPluginOptions interface {
|
type ClientPluginOptions interface {
|
||||||
@@ -109,6 +111,13 @@ type HTTP2HTTPSPluginOptions struct {
|
|||||||
|
|
||||||
func (o *HTTP2HTTPSPluginOptions) Complete() {}
|
func (o *HTTP2HTTPSPluginOptions) Complete() {}
|
||||||
|
|
||||||
|
type HTTP2HTTPSRedirectPluginOptions struct {
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
HTTPSPort int `json:"httpsPort,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *HTTP2HTTPSRedirectPluginOptions) Complete() {}
|
||||||
|
|
||||||
type HTTPProxyPluginOptions struct {
|
type HTTPProxyPluginOptions struct {
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
HTTPUser string `json:"httpUser,omitempty"`
|
HTTPUser string `json:"httpUser,omitempty"`
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ func ValidateClientPluginOptions(c v1.ClientPluginOptions) error {
|
|||||||
switch v := c.(type) {
|
switch v := c.(type) {
|
||||||
case *v1.HTTP2HTTPSPluginOptions:
|
case *v1.HTTP2HTTPSPluginOptions:
|
||||||
return validateHTTP2HTTPSPluginOptions(v)
|
return validateHTTP2HTTPSPluginOptions(v)
|
||||||
|
case *v1.HTTP2HTTPSRedirectPluginOptions:
|
||||||
|
return validateHTTP2HTTPSRedirectPluginOptions(v)
|
||||||
case *v1.HTTPS2HTTPPluginOptions:
|
case *v1.HTTPS2HTTPPluginOptions:
|
||||||
return validateHTTPS2HTTPPluginOptions(v)
|
return validateHTTPS2HTTPPluginOptions(v)
|
||||||
case *v1.HTTPS2HTTPSPluginOptions:
|
case *v1.HTTPS2HTTPSPluginOptions:
|
||||||
@@ -47,6 +49,10 @@ func validateHTTP2HTTPSPluginOptions(c *v1.HTTP2HTTPSPluginOptions) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateHTTP2HTTPSRedirectPluginOptions(c *v1.HTTP2HTTPSRedirectPluginOptions) error {
|
||||||
|
return ValidatePort(c.HTTPSPort, "httpsPort")
|
||||||
|
}
|
||||||
|
|
||||||
func validateHTTPS2HTTPPluginOptions(c *v1.HTTPS2HTTPPluginOptions) error {
|
func validateHTTPS2HTTPPluginOptions(c *v1.HTTPS2HTTPPluginOptions) error {
|
||||||
if c.LocalAddr == "" {
|
if c.LocalAddr == "" {
|
||||||
return errors.New("localAddr is required")
|
return errors.New("localAddr is required")
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2026 The frp Authors
|
// Copyright 2026 The LoliaTeam Authors
|
||||||
//
|
//
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
109
pkg/plugin/client/http2https_redirect.go
Normal file
109
pkg/plugin/client/http2https_redirect.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
// Copyright 2026 The LoliaTeam Authors
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
//go:build !frps
|
||||||
|
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
v1 "github.com/fatedier/frp/pkg/config/v1"
|
||||||
|
netpkg "github.com/fatedier/frp/pkg/util/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Register(v1.PluginHTTP2HTTPSRedirect, NewHTTP2HTTPSRedirectPlugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
type HTTP2HTTPSRedirectPlugin struct {
|
||||||
|
opts *v1.HTTP2HTTPSRedirectPluginOptions
|
||||||
|
|
||||||
|
l *Listener
|
||||||
|
s *http.Server
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHTTP2HTTPSRedirectPlugin(_ PluginContext, options v1.ClientPluginOptions) (Plugin, error) {
|
||||||
|
opts := options.(*v1.HTTP2HTTPSRedirectPluginOptions)
|
||||||
|
|
||||||
|
listener := NewProxyListener()
|
||||||
|
p := &HTTP2HTTPSRedirectPlugin{
|
||||||
|
opts: opts,
|
||||||
|
l: listener,
|
||||||
|
}
|
||||||
|
|
||||||
|
p.s = &http.Server{
|
||||||
|
Handler: http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
http.Redirect(w, req, buildHTTPSRedirectURL(req, opts.HTTPSPort), http.StatusFound)
|
||||||
|
}),
|
||||||
|
ReadHeaderTimeout: 60 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
_ = p.s.Serve(listener)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildHTTPSRedirectURL(req *http.Request, httpsPort int) string {
|
||||||
|
host := strings.TrimSpace(req.Host)
|
||||||
|
if host == "" {
|
||||||
|
host = strings.TrimSpace(req.URL.Host)
|
||||||
|
}
|
||||||
|
|
||||||
|
targetHost := host
|
||||||
|
if parsedHost, parsedPort, err := net.SplitHostPort(host); err == nil {
|
||||||
|
targetHost = parsedHost
|
||||||
|
if httpsPort == 0 && parsedPort == "443" {
|
||||||
|
httpsPort = 443
|
||||||
|
}
|
||||||
|
} else if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
|
||||||
|
targetHost = strings.TrimSuffix(strings.TrimPrefix(host, "["), "]")
|
||||||
|
}
|
||||||
|
|
||||||
|
if httpsPort != 0 && httpsPort != 443 {
|
||||||
|
targetHost = net.JoinHostPort(targetHost, strconv.Itoa(httpsPort))
|
||||||
|
}
|
||||||
|
|
||||||
|
return (&url.URL{
|
||||||
|
Scheme: "https",
|
||||||
|
Host: targetHost,
|
||||||
|
Path: req.URL.Path,
|
||||||
|
RawPath: req.URL.RawPath,
|
||||||
|
RawQuery: req.URL.RawQuery,
|
||||||
|
}).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *HTTP2HTTPSRedirectPlugin) Handle(_ context.Context, connInfo *ConnectionInfo) {
|
||||||
|
wrapConn := netpkg.WrapReadWriteCloserToConn(connInfo.Conn, connInfo.UnderlyingConn)
|
||||||
|
if connInfo.SrcAddr != nil {
|
||||||
|
wrapConn.SetRemoteAddr(connInfo.SrcAddr)
|
||||||
|
}
|
||||||
|
_ = p.l.PutConn(wrapConn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *HTTP2HTTPSRedirectPlugin) Name() string {
|
||||||
|
return v1.PluginHTTP2HTTPSRedirect
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *HTTP2HTTPSRedirectPlugin) Close() error {
|
||||||
|
return p.s.Close()
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
package version
|
package version
|
||||||
|
|
||||||
var version = "LoliaFRP-CLI 0.67.3"
|
var version = "LoliaFRP-CLI 0.67.4"
|
||||||
|
|
||||||
func Full() string {
|
func Full() string {
|
||||||
return version
|
return version
|
||||||
|
|||||||
Reference in New Issue
Block a user