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"
|
||||
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]]
|
||||
name = "plugin_http2http"
|
||||
type = "tcp"
|
||||
|
||||
@@ -27,29 +27,31 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
PluginHTTP2HTTPS = "http2https"
|
||||
PluginHTTPProxy = "http_proxy"
|
||||
PluginHTTPS2HTTP = "https2http"
|
||||
PluginHTTPS2HTTPS = "https2https"
|
||||
PluginHTTP2HTTP = "http2http"
|
||||
PluginSocks5 = "socks5"
|
||||
PluginStaticFile = "static_file"
|
||||
PluginUnixDomainSocket = "unix_domain_socket"
|
||||
PluginTLS2Raw = "tls2raw"
|
||||
PluginVirtualNet = "virtual_net"
|
||||
PluginHTTP2HTTPS = "http2https"
|
||||
PluginHTTP2HTTPSRedirect = "http2https_redirect"
|
||||
PluginHTTPProxy = "http_proxy"
|
||||
PluginHTTPS2HTTP = "https2http"
|
||||
PluginHTTPS2HTTPS = "https2https"
|
||||
PluginHTTP2HTTP = "http2http"
|
||||
PluginSocks5 = "socks5"
|
||||
PluginStaticFile = "static_file"
|
||||
PluginUnixDomainSocket = "unix_domain_socket"
|
||||
PluginTLS2Raw = "tls2raw"
|
||||
PluginVirtualNet = "virtual_net"
|
||||
)
|
||||
|
||||
var clientPluginOptionsTypeMap = map[string]reflect.Type{
|
||||
PluginHTTP2HTTPS: reflect.TypeOf(HTTP2HTTPSPluginOptions{}),
|
||||
PluginHTTPProxy: reflect.TypeOf(HTTPProxyPluginOptions{}),
|
||||
PluginHTTPS2HTTP: reflect.TypeOf(HTTPS2HTTPPluginOptions{}),
|
||||
PluginHTTPS2HTTPS: reflect.TypeOf(HTTPS2HTTPSPluginOptions{}),
|
||||
PluginHTTP2HTTP: reflect.TypeOf(HTTP2HTTPPluginOptions{}),
|
||||
PluginSocks5: reflect.TypeOf(Socks5PluginOptions{}),
|
||||
PluginStaticFile: reflect.TypeOf(StaticFilePluginOptions{}),
|
||||
PluginUnixDomainSocket: reflect.TypeOf(UnixDomainSocketPluginOptions{}),
|
||||
PluginTLS2Raw: reflect.TypeOf(TLS2RawPluginOptions{}),
|
||||
PluginVirtualNet: reflect.TypeOf(VirtualNetPluginOptions{}),
|
||||
PluginHTTP2HTTPS: reflect.TypeOf(HTTP2HTTPSPluginOptions{}),
|
||||
PluginHTTP2HTTPSRedirect: reflect.TypeOf(HTTP2HTTPSRedirectPluginOptions{}),
|
||||
PluginHTTPProxy: reflect.TypeOf(HTTPProxyPluginOptions{}),
|
||||
PluginHTTPS2HTTP: reflect.TypeOf(HTTPS2HTTPPluginOptions{}),
|
||||
PluginHTTPS2HTTPS: reflect.TypeOf(HTTPS2HTTPSPluginOptions{}),
|
||||
PluginHTTP2HTTP: reflect.TypeOf(HTTP2HTTPPluginOptions{}),
|
||||
PluginSocks5: reflect.TypeOf(Socks5PluginOptions{}),
|
||||
PluginStaticFile: reflect.TypeOf(StaticFilePluginOptions{}),
|
||||
PluginUnixDomainSocket: reflect.TypeOf(UnixDomainSocketPluginOptions{}),
|
||||
PluginTLS2Raw: reflect.TypeOf(TLS2RawPluginOptions{}),
|
||||
PluginVirtualNet: reflect.TypeOf(VirtualNetPluginOptions{}),
|
||||
}
|
||||
|
||||
type ClientPluginOptions interface {
|
||||
@@ -109,6 +111,13 @@ type HTTP2HTTPSPluginOptions struct {
|
||||
|
||||
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 string `json:"type,omitempty"`
|
||||
HTTPUser string `json:"httpUser,omitempty"`
|
||||
|
||||
@@ -26,6 +26,8 @@ func ValidateClientPluginOptions(c v1.ClientPluginOptions) error {
|
||||
switch v := c.(type) {
|
||||
case *v1.HTTP2HTTPSPluginOptions:
|
||||
return validateHTTP2HTTPSPluginOptions(v)
|
||||
case *v1.HTTP2HTTPSRedirectPluginOptions:
|
||||
return validateHTTP2HTTPSRedirectPluginOptions(v)
|
||||
case *v1.HTTPS2HTTPPluginOptions:
|
||||
return validateHTTPS2HTTPPluginOptions(v)
|
||||
case *v1.HTTPS2HTTPSPluginOptions:
|
||||
@@ -47,6 +49,10 @@ func validateHTTP2HTTPSPluginOptions(c *v1.HTTP2HTTPSPluginOptions) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateHTTP2HTTPSRedirectPluginOptions(c *v1.HTTP2HTTPSRedirectPluginOptions) error {
|
||||
return ValidatePort(c.HTTPSPort, "httpsPort")
|
||||
}
|
||||
|
||||
func validateHTTPS2HTTPPluginOptions(c *v1.HTTPS2HTTPPluginOptions) error {
|
||||
if c.LocalAddr == "" {
|
||||
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");
|
||||
// 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
|
||||
|
||||
var version = "LoliaFRP-CLI 0.67.3"
|
||||
var version = "LoliaFRP-CLI 0.67.4"
|
||||
|
||||
func Full() string {
|
||||
return version
|
||||
|
||||
Reference in New Issue
Block a user