Skip to content

Commit

Permalink
Merge pull request #3010 from fatedier/dev
Browse files Browse the repository at this point in the history
release v0.44.0
  • Loading branch information
fatedier authored Jul 10, 2022
2 parents fe5fb03 + fa7c05c commit 8888610
Show file tree
Hide file tree
Showing 13 changed files with 142 additions and 63 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,21 @@ dashboard_pwd = admin

Then visit `http://[server_addr]:7500` to see the dashboard, with username and password both being `admin`.

Additionally, you can use HTTPS port by using your domains wildcard or normal SSL certificate:

```ini
[common]
dashboard_port = 7500
# dashboard's username and password are both optional
dashboard_user = admin
dashboard_pwd = admin
dashboard_tls_mode = true
dashboard_tls_cert_file = server.crt
dashboard_tls_key_file = server.key
```

Then visit `https://[server_addr]:7500` to see the dashboard in secure HTTPS connection, with username and password both being `admin`.

![dashboard](/doc/pic/dashboard.png)

### Admin UI
Expand Down
9 changes: 6 additions & 3 deletions Release.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
### New

* Added `route_by_http_user` in `http` and `tcpmux` proxy to support route to different clients by HTTP basic auth user.
* `CONNECT` method can be forwarded in `http` type proxy.
* Added `tcpmux_passthrough` in `tcpmux` proxy. If true, `CONNECT` request will be forwarded to frpc.
* Use auto generated certificates if `plugin_key_path` and `plugin_crt_path` are empty for plugin `https2https` and `https2http`.
* Server dashboard supports TLS configs.

### Fix

* xtcp error with IPv6 address.
20 changes: 11 additions & 9 deletions client/admin_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ import (
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"os"
"sort"
"strconv"
"strings"

"github.com/fatedier/frp/client/proxy"
Expand Down Expand Up @@ -105,48 +107,48 @@ func NewProxyStatusResp(status *proxy.WorkingStatus, serverAddr string) ProxySta
switch cfg := status.Cfg.(type) {
case *config.TCPProxyConf:
if cfg.LocalPort != 0 {
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
}
psr.Plugin = cfg.Plugin
if status.Err != "" {
psr.RemoteAddr = fmt.Sprintf("%s:%d", serverAddr, cfg.RemotePort)
psr.RemoteAddr = net.JoinHostPort(serverAddr, strconv.Itoa(cfg.RemotePort))
} else {
psr.RemoteAddr = serverAddr + status.RemoteAddr
}
case *config.UDPProxyConf:
if cfg.LocalPort != 0 {
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
}
if status.Err != "" {
psr.RemoteAddr = fmt.Sprintf("%s:%d", serverAddr, cfg.RemotePort)
psr.RemoteAddr = net.JoinHostPort(serverAddr, strconv.Itoa(cfg.RemotePort))
} else {
psr.RemoteAddr = serverAddr + status.RemoteAddr
}
case *config.HTTPProxyConf:
if cfg.LocalPort != 0 {
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
}
psr.Plugin = cfg.Plugin
psr.RemoteAddr = status.RemoteAddr
case *config.HTTPSProxyConf:
if cfg.LocalPort != 0 {
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
}
psr.Plugin = cfg.Plugin
psr.RemoteAddr = status.RemoteAddr
case *config.STCPProxyConf:
if cfg.LocalPort != 0 {
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
}
psr.Plugin = cfg.Plugin
case *config.XTCPProxyConf:
if cfg.LocalPort != 0 {
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
}
psr.Plugin = cfg.Plugin
case *config.SUDPProxyConf:
if cfg.LocalPort != 0 {
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
}
psr.Plugin = cfg.Plugin
}
Expand Down
9 changes: 4 additions & 5 deletions client/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package proxy
import (
"bytes"
"context"
"fmt"
"io"
"net"
"strconv"
Expand Down Expand Up @@ -307,7 +306,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
Sid: natHoleSidMsg.Sid,
}
raddr, _ := net.ResolveUDPAddr("udp",
fmt.Sprintf("%s:%d", pxy.clientCfg.ServerAddr, pxy.serverUDPPort))
net.JoinHostPort(pxy.clientCfg.ServerAddr, strconv.Itoa(pxy.serverUDPPort)))
clientConn, err := net.DialUDP("udp", nil, raddr)
if err != nil {
xl.Error("dial server udp addr error: %v", err)
Expand Down Expand Up @@ -415,7 +414,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
}

func (pxy *XTCPProxy) sendDetectMsg(addr string, port int, laddr *net.UDPAddr, content []byte) (err error) {
daddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", addr, port))
daddr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(addr, strconv.Itoa(port)))
if err != nil {
return err
}
Expand Down Expand Up @@ -448,7 +447,7 @@ type UDPProxy struct {
}

func (pxy *UDPProxy) Run() (err error) {
pxy.localAddr, err = net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", pxy.cfg.LocalIP, pxy.cfg.LocalPort))
pxy.localAddr, err = net.ResolveUDPAddr("udp", net.JoinHostPort(pxy.cfg.LocalIP, strconv.Itoa(pxy.cfg.LocalPort)))
if err != nil {
return
}
Expand Down Expand Up @@ -570,7 +569,7 @@ type SUDPProxy struct {
}

func (pxy *SUDPProxy) Run() (err error) {
pxy.localAddr, err = net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", pxy.cfg.LocalIP, pxy.cfg.LocalPort))
pxy.localAddr, err = net.ResolveUDPAddr("udp", net.JoinHostPort(pxy.cfg.LocalIP, strconv.Itoa(pxy.cfg.LocalPort)))
if err != nil {
return
}
Expand Down
2 changes: 1 addition & 1 deletion client/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
}

raddr, err := net.ResolveUDPAddr("udp",
fmt.Sprintf("%s:%d", sv.ctl.clientCfg.ServerAddr, sv.ctl.serverUDPPort))
net.JoinHostPort(sv.ctl.clientCfg.ServerAddr, strconv.Itoa(sv.ctl.serverUDPPort)))
if err != nil {
xl.Error("resolve server UDP addr error")
return
Expand Down
59 changes: 34 additions & 25 deletions cmd/frps/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,31 +37,34 @@ var (
cfgFile string
showVersion bool

bindAddr string
bindPort int
bindUDPPort int
kcpBindPort int
proxyBindAddr string
vhostHTTPPort int
vhostHTTPSPort int
vhostHTTPTimeout int64
dashboardAddr string
dashboardPort int
dashboardUser string
dashboardPwd string
enablePrometheus bool
assetsDir string
logFile string
logLevel string
logMaxDays int64
disableLogColor bool
token string
subDomainHost string
tcpMux bool
allowPorts string
maxPoolCount int64
maxPortsPerClient int64
tlsOnly bool
bindAddr string
bindPort int
bindUDPPort int
kcpBindPort int
proxyBindAddr string
vhostHTTPPort int
vhostHTTPSPort int
vhostHTTPTimeout int64
dashboardAddr string
dashboardPort int
dashboardUser string
dashboardPwd string
enablePrometheus bool
assetsDir string
logFile string
logLevel string
logMaxDays int64
disableLogColor bool
token string
subDomainHost string
tcpMux bool
allowPorts string
maxPoolCount int64
maxPortsPerClient int64
tlsOnly bool
dashboardTLSMode bool
dashboardTLSCertFile string
dashboardTLSKeyFile string
)

func init() {
Expand Down Expand Up @@ -91,6 +94,9 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&allowPorts, "allow_ports", "", "", "allow ports")
rootCmd.PersistentFlags().Int64VarP(&maxPortsPerClient, "max_ports_per_client", "", 0, "max ports per client")
rootCmd.PersistentFlags().BoolVarP(&tlsOnly, "tls_only", "", false, "frps tls only")
rootCmd.PersistentFlags().BoolVarP(&dashboardTLSMode, "dashboard_tls_mode", "", false, "dashboard tls mode")
rootCmd.PersistentFlags().StringVarP(&dashboardTLSCertFile, "dashboard_tls_cert_file", "", "", "dashboard tls cert file")
rootCmd.PersistentFlags().StringVarP(&dashboardTLSKeyFile, "dashboard_tls_key_file", "", "", "dashboard tls key file")
}

var rootCmd = &cobra.Command{
Expand Down Expand Up @@ -167,6 +173,9 @@ func parseServerCommonCfgFromCmd() (cfg config.ServerCommonConf, err error) {
cfg.DashboardUser = dashboardUser
cfg.DashboardPwd = dashboardPwd
cfg.EnablePrometheus = enablePrometheus
cfg.DashboardTLSCertFile = dashboardTLSCertFile
cfg.DashboardTLSKeyFile = dashboardTLSKeyFile
cfg.DashboardTLSMode = dashboardTLSMode
cfg.LogFile = logFile
cfg.LogLevel = logLevel
cfg.LogMaxDays = logMaxDays
Expand Down
5 changes: 5 additions & 0 deletions conf/frps_full.ini
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ dashboard_port = 7500
dashboard_user = admin
dashboard_pwd = admin

# dashboard TLS mode
dashboard_tls_mode = false
# dashboard_tls_cert_file = server.crt
# dashboard_tls_key_file = server.key

# enable_prometheus will export prometheus metrics on {dashboard_addr}:{dashboard_port} in /metrics api.
enable_prometheus = true

Expand Down
4 changes: 3 additions & 1 deletion pkg/config/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ package config

import (
"fmt"
"net"
"reflect"
"strconv"
"strings"

"github.com/fatedier/frp/pkg/consts"
Expand Down Expand Up @@ -372,7 +374,7 @@ func (cfg *BaseProxyConf) decorate(prefix string, name string, section *ini.Sect
}

if cfg.HealthCheckType == "http" && cfg.Plugin == "" && cfg.HealthCheckURL != "" {
s := fmt.Sprintf("http://%s:%d", cfg.LocalIP, cfg.LocalPort)
s := "http://" + net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
if !strings.HasPrefix(cfg.HealthCheckURL, "/") {
s += "/"
}
Expand Down
28 changes: 28 additions & 0 deletions pkg/config/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ type ServerCommonConf struct {
// value is 0, the dashboard will not be started. By default, this value is
// 0.
DashboardPort int `ini:"dashboard_port" json:"dashboard_port" validate:"gte=0,lte=65535"`
// DashboardTLSCertFile specifies the path of the cert file that the server will
// load. If "dashboard_tls_cert_file", "dashboard_tls_key_file" are valid, the server will use this
// supplied tls configuration.
DashboardTLSCertFile string `ini:"dashboard_tls_cert_file" json:"dashboard_tls_cert_file"`
// DashboardTLSKeyFile specifies the path of the secret key that the server will
// load. If "dashboard_tls_cert_file", "dashboard_tls_key_file" are valid, the server will use this
// supplied tls configuration.
DashboardTLSKeyFile string `ini:"dashboard_tls_key_file" json:"dashboard_tls_key_file"`
// DashboardTLSMode specifies the mode of the dashboard between HTTP or HTTPS modes. By
// default, this value is false, which is HTTP mode.
DashboardTLSMode bool `ini:"dashboard_tls_mode" json:"dashboard_tls_mode"`
// DashboardUser specifies the username that the dashboard will use for
// login.
DashboardUser string `ini:"dashboard_user" json:"dashboard_user"`
Expand Down Expand Up @@ -297,6 +308,23 @@ func (cfg *ServerCommonConf) Complete() {
}

func (cfg *ServerCommonConf) Validate() error {
if cfg.DashboardTLSMode == false {
if cfg.DashboardTLSCertFile != "" {
fmt.Println("WARNING! dashboard_tls_cert_file is invalid when dashboard_tls_mode is false")
}

if cfg.DashboardTLSKeyFile != "" {
fmt.Println("WARNING! dashboard_tls_key_file is invalid when dashboard_tls_mode is false")
}
} else {
if cfg.DashboardTLSCertFile == "" {
return fmt.Errorf("ERROR! dashboard_tls_cert_file must be specified when dashboard_tls_mode is true")
}

if cfg.DashboardTLSKeyFile == "" {
return fmt.Errorf("ERROR! dashboard_tls_cert_file must be specified when dashboard_tls_mode is true")
}
}
return validator.New().Struct(cfg)
}

Expand Down
18 changes: 11 additions & 7 deletions pkg/plugin/client/https2http.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"net/http/httputil"
"strings"

"github.com/fatedier/frp/pkg/transport"
frpNet "github.com/fatedier/frp/pkg/util/net"
)

Expand Down Expand Up @@ -58,12 +59,6 @@ func NewHTTPS2HTTPPlugin(params map[string]string) (Plugin, error) {
}
}

if crtPath == "" {
return nil, fmt.Errorf("plugin_crt_path is required")
}
if keyPath == "" {
return nil, fmt.Errorf("plugin_key_path is required")
}
if localAddr == "" {
return nil, fmt.Errorf("plugin_local_addr is required")
}
Expand Down Expand Up @@ -96,7 +91,16 @@ func NewHTTPS2HTTPPlugin(params map[string]string) (Plugin, error) {
Handler: rp,
}

tlsConfig, err := p.genTLSConfig()
var (
tlsConfig *tls.Config
err error
)
if crtPath != "" || keyPath != "" {
tlsConfig, err = p.genTLSConfig()
} else {
tlsConfig, err = transport.NewServerTLSConfig("", "", "")
tlsConfig.InsecureSkipVerify = true
}
if err != nil {
return nil, fmt.Errorf("gen TLS config error: %v", err)
}
Expand Down
20 changes: 12 additions & 8 deletions pkg/plugin/client/https2https.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"net/http/httputil"
"strings"

"github.com/fatedier/frp/pkg/transport"
frpNet "github.com/fatedier/frp/pkg/util/net"
)

Expand Down Expand Up @@ -58,12 +59,6 @@ func NewHTTPS2HTTPSPlugin(params map[string]string) (Plugin, error) {
}
}

if crtPath == "" {
return nil, fmt.Errorf("plugin_crt_path is required")
}
if keyPath == "" {
return nil, fmt.Errorf("plugin_key_path is required")
}
if localAddr == "" {
return nil, fmt.Errorf("plugin_local_addr is required")
}
Expand Down Expand Up @@ -101,7 +96,16 @@ func NewHTTPS2HTTPSPlugin(params map[string]string) (Plugin, error) {
Handler: rp,
}

tlsConfig, err := p.genTLSConfig()
var (
tlsConfig *tls.Config
err error
)
if crtPath != "" || keyPath != "" {
tlsConfig, err = p.genTLSConfig()
} else {
tlsConfig, err = transport.NewServerTLSConfig("", "", "")
tlsConfig.InsecureSkipVerify = true
}
if err != nil {
return nil, fmt.Errorf("gen TLS config error: %v", err)
}
Expand All @@ -127,7 +131,7 @@ func (p *HTTPS2HTTPSPlugin) Handle(conn io.ReadWriteCloser, realConn net.Conn, e
}

func (p *HTTPS2HTTPSPlugin) Name() string {
return PluginHTTPS2HTTP
return PluginHTTPS2HTTPS
}

func (p *HTTPS2HTTPSPlugin) Close() error {
Expand Down
Loading

0 comments on commit 8888610

Please sign in to comment.