Skip to content

Commit 8888610

Browse files
authored
Merge pull request #3010 from fatedier/dev
release v0.44.0
2 parents fe5fb03 + fa7c05c commit 8888610

File tree

13 files changed

+142
-63
lines changed

13 files changed

+142
-63
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,21 @@ dashboard_pwd = admin
477477

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

480+
Additionally, you can use HTTPS port by using your domains wildcard or normal SSL certificate:
481+
482+
```ini
483+
[common]
484+
dashboard_port = 7500
485+
# dashboard's username and password are both optional
486+
dashboard_user = admin
487+
dashboard_pwd = admin
488+
dashboard_tls_mode = true
489+
dashboard_tls_cert_file = server.crt
490+
dashboard_tls_key_file = server.key
491+
```
492+
493+
Then visit `https://[server_addr]:7500` to see the dashboard in secure HTTPS connection, with username and password both being `admin`.
494+
480495
![dashboard](/doc/pic/dashboard.png)
481496

482497
### Admin UI

Release.md

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

3-
* Added `route_by_http_user` in `http` and `tcpmux` proxy to support route to different clients by HTTP basic auth user.
4-
* `CONNECT` method can be forwarded in `http` type proxy.
5-
* Added `tcpmux_passthrough` in `tcpmux` proxy. If true, `CONNECT` request will be forwarded to frpc.
3+
* Use auto generated certificates if `plugin_key_path` and `plugin_crt_path` are empty for plugin `https2https` and `https2http`.
4+
* Server dashboard supports TLS configs.
5+
6+
### Fix
7+
8+
* xtcp error with IPv6 address.

client/admin_api.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ import (
1818
"encoding/json"
1919
"fmt"
2020
"io"
21+
"net"
2122
"net/http"
2223
"os"
2324
"sort"
25+
"strconv"
2426
"strings"
2527

2628
"github.com/fatedier/frp/client/proxy"
@@ -105,48 +107,48 @@ func NewProxyStatusResp(status *proxy.WorkingStatus, serverAddr string) ProxySta
105107
switch cfg := status.Cfg.(type) {
106108
case *config.TCPProxyConf:
107109
if cfg.LocalPort != 0 {
108-
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
110+
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
109111
}
110112
psr.Plugin = cfg.Plugin
111113
if status.Err != "" {
112-
psr.RemoteAddr = fmt.Sprintf("%s:%d", serverAddr, cfg.RemotePort)
114+
psr.RemoteAddr = net.JoinHostPort(serverAddr, strconv.Itoa(cfg.RemotePort))
113115
} else {
114116
psr.RemoteAddr = serverAddr + status.RemoteAddr
115117
}
116118
case *config.UDPProxyConf:
117119
if cfg.LocalPort != 0 {
118-
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
120+
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
119121
}
120122
if status.Err != "" {
121-
psr.RemoteAddr = fmt.Sprintf("%s:%d", serverAddr, cfg.RemotePort)
123+
psr.RemoteAddr = net.JoinHostPort(serverAddr, strconv.Itoa(cfg.RemotePort))
122124
} else {
123125
psr.RemoteAddr = serverAddr + status.RemoteAddr
124126
}
125127
case *config.HTTPProxyConf:
126128
if cfg.LocalPort != 0 {
127-
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
129+
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
128130
}
129131
psr.Plugin = cfg.Plugin
130132
psr.RemoteAddr = status.RemoteAddr
131133
case *config.HTTPSProxyConf:
132134
if cfg.LocalPort != 0 {
133-
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
135+
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
134136
}
135137
psr.Plugin = cfg.Plugin
136138
psr.RemoteAddr = status.RemoteAddr
137139
case *config.STCPProxyConf:
138140
if cfg.LocalPort != 0 {
139-
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
141+
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
140142
}
141143
psr.Plugin = cfg.Plugin
142144
case *config.XTCPProxyConf:
143145
if cfg.LocalPort != 0 {
144-
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
146+
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
145147
}
146148
psr.Plugin = cfg.Plugin
147149
case *config.SUDPProxyConf:
148150
if cfg.LocalPort != 0 {
149-
psr.LocalAddr = fmt.Sprintf("%s:%d", cfg.LocalIP, cfg.LocalPort)
151+
psr.LocalAddr = net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
150152
}
151153
psr.Plugin = cfg.Plugin
152154
}

client/proxy/proxy.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ package proxy
1717
import (
1818
"bytes"
1919
"context"
20-
"fmt"
2120
"io"
2221
"net"
2322
"strconv"
@@ -307,7 +306,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
307306
Sid: natHoleSidMsg.Sid,
308307
}
309308
raddr, _ := net.ResolveUDPAddr("udp",
310-
fmt.Sprintf("%s:%d", pxy.clientCfg.ServerAddr, pxy.serverUDPPort))
309+
net.JoinHostPort(pxy.clientCfg.ServerAddr, strconv.Itoa(pxy.serverUDPPort)))
311310
clientConn, err := net.DialUDP("udp", nil, raddr)
312311
if err != nil {
313312
xl.Error("dial server udp addr error: %v", err)
@@ -415,7 +414,7 @@ func (pxy *XTCPProxy) InWorkConn(conn net.Conn, m *msg.StartWorkConn) {
415414
}
416415

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

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

572571
func (pxy *SUDPProxy) Run() (err error) {
573-
pxy.localAddr, err = net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", pxy.cfg.LocalIP, pxy.cfg.LocalPort))
572+
pxy.localAddr, err = net.ResolveUDPAddr("udp", net.JoinHostPort(pxy.cfg.LocalIP, strconv.Itoa(pxy.cfg.LocalPort)))
574573
if err != nil {
575574
return
576575
}

client/visitor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ func (sv *XTCPVisitor) handleConn(userConn net.Conn) {
212212
}
213213

214214
raddr, err := net.ResolveUDPAddr("udp",
215-
fmt.Sprintf("%s:%d", sv.ctl.clientCfg.ServerAddr, sv.ctl.serverUDPPort))
215+
net.JoinHostPort(sv.ctl.clientCfg.ServerAddr, strconv.Itoa(sv.ctl.serverUDPPort)))
216216
if err != nil {
217217
xl.Error("resolve server UDP addr error")
218218
return

cmd/frps/root.go

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -37,31 +37,34 @@ var (
3737
cfgFile string
3838
showVersion bool
3939

40-
bindAddr string
41-
bindPort int
42-
bindUDPPort int
43-
kcpBindPort int
44-
proxyBindAddr string
45-
vhostHTTPPort int
46-
vhostHTTPSPort int
47-
vhostHTTPTimeout int64
48-
dashboardAddr string
49-
dashboardPort int
50-
dashboardUser string
51-
dashboardPwd string
52-
enablePrometheus bool
53-
assetsDir string
54-
logFile string
55-
logLevel string
56-
logMaxDays int64
57-
disableLogColor bool
58-
token string
59-
subDomainHost string
60-
tcpMux bool
61-
allowPorts string
62-
maxPoolCount int64
63-
maxPortsPerClient int64
64-
tlsOnly bool
40+
bindAddr string
41+
bindPort int
42+
bindUDPPort int
43+
kcpBindPort int
44+
proxyBindAddr string
45+
vhostHTTPPort int
46+
vhostHTTPSPort int
47+
vhostHTTPTimeout int64
48+
dashboardAddr string
49+
dashboardPort int
50+
dashboardUser string
51+
dashboardPwd string
52+
enablePrometheus bool
53+
assetsDir string
54+
logFile string
55+
logLevel string
56+
logMaxDays int64
57+
disableLogColor bool
58+
token string
59+
subDomainHost string
60+
tcpMux bool
61+
allowPorts string
62+
maxPoolCount int64
63+
maxPortsPerClient int64
64+
tlsOnly bool
65+
dashboardTLSMode bool
66+
dashboardTLSCertFile string
67+
dashboardTLSKeyFile string
6568
)
6669

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

96102
var rootCmd = &cobra.Command{
@@ -167,6 +173,9 @@ func parseServerCommonCfgFromCmd() (cfg config.ServerCommonConf, err error) {
167173
cfg.DashboardUser = dashboardUser
168174
cfg.DashboardPwd = dashboardPwd
169175
cfg.EnablePrometheus = enablePrometheus
176+
cfg.DashboardTLSCertFile = dashboardTLSCertFile
177+
cfg.DashboardTLSKeyFile = dashboardTLSKeyFile
178+
cfg.DashboardTLSMode = dashboardTLSMode
170179
cfg.LogFile = logFile
171180
cfg.LogLevel = logLevel
172181
cfg.LogMaxDays = logMaxDays

conf/frps_full.ini

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ dashboard_port = 7500
4343
dashboard_user = admin
4444
dashboard_pwd = admin
4545

46+
# dashboard TLS mode
47+
dashboard_tls_mode = false
48+
# dashboard_tls_cert_file = server.crt
49+
# dashboard_tls_key_file = server.key
50+
4651
# enable_prometheus will export prometheus metrics on {dashboard_addr}:{dashboard_port} in /metrics api.
4752
enable_prometheus = true
4853

pkg/config/proxy.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ package config
1616

1717
import (
1818
"fmt"
19+
"net"
1920
"reflect"
21+
"strconv"
2022
"strings"
2123

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

374376
if cfg.HealthCheckType == "http" && cfg.Plugin == "" && cfg.HealthCheckURL != "" {
375-
s := fmt.Sprintf("http://%s:%d", cfg.LocalIP, cfg.LocalPort)
377+
s := "http://" + net.JoinHostPort(cfg.LocalIP, strconv.Itoa(cfg.LocalPort))
376378
if !strings.HasPrefix(cfg.HealthCheckURL, "/") {
377379
s += "/"
378380
}

pkg/config/server.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,17 @@ type ServerCommonConf struct {
7474
// value is 0, the dashboard will not be started. By default, this value is
7575
// 0.
7676
DashboardPort int `ini:"dashboard_port" json:"dashboard_port" validate:"gte=0,lte=65535"`
77+
// DashboardTLSCertFile specifies the path of the cert file that the server will
78+
// load. If "dashboard_tls_cert_file", "dashboard_tls_key_file" are valid, the server will use this
79+
// supplied tls configuration.
80+
DashboardTLSCertFile string `ini:"dashboard_tls_cert_file" json:"dashboard_tls_cert_file"`
81+
// DashboardTLSKeyFile specifies the path of the secret key that the server will
82+
// load. If "dashboard_tls_cert_file", "dashboard_tls_key_file" are valid, the server will use this
83+
// supplied tls configuration.
84+
DashboardTLSKeyFile string `ini:"dashboard_tls_key_file" json:"dashboard_tls_key_file"`
85+
// DashboardTLSMode specifies the mode of the dashboard between HTTP or HTTPS modes. By
86+
// default, this value is false, which is HTTP mode.
87+
DashboardTLSMode bool `ini:"dashboard_tls_mode" json:"dashboard_tls_mode"`
7788
// DashboardUser specifies the username that the dashboard will use for
7889
// login.
7990
DashboardUser string `ini:"dashboard_user" json:"dashboard_user"`
@@ -297,6 +308,23 @@ func (cfg *ServerCommonConf) Complete() {
297308
}
298309

299310
func (cfg *ServerCommonConf) Validate() error {
311+
if cfg.DashboardTLSMode == false {
312+
if cfg.DashboardTLSCertFile != "" {
313+
fmt.Println("WARNING! dashboard_tls_cert_file is invalid when dashboard_tls_mode is false")
314+
}
315+
316+
if cfg.DashboardTLSKeyFile != "" {
317+
fmt.Println("WARNING! dashboard_tls_key_file is invalid when dashboard_tls_mode is false")
318+
}
319+
} else {
320+
if cfg.DashboardTLSCertFile == "" {
321+
return fmt.Errorf("ERROR! dashboard_tls_cert_file must be specified when dashboard_tls_mode is true")
322+
}
323+
324+
if cfg.DashboardTLSKeyFile == "" {
325+
return fmt.Errorf("ERROR! dashboard_tls_cert_file must be specified when dashboard_tls_mode is true")
326+
}
327+
}
300328
return validator.New().Struct(cfg)
301329
}
302330

pkg/plugin/client/https2http.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"net/http/httputil"
2424
"strings"
2525

26+
"github.com/fatedier/frp/pkg/transport"
2627
frpNet "github.com/fatedier/frp/pkg/util/net"
2728
)
2829

@@ -58,12 +59,6 @@ func NewHTTPS2HTTPPlugin(params map[string]string) (Plugin, error) {
5859
}
5960
}
6061

61-
if crtPath == "" {
62-
return nil, fmt.Errorf("plugin_crt_path is required")
63-
}
64-
if keyPath == "" {
65-
return nil, fmt.Errorf("plugin_key_path is required")
66-
}
6762
if localAddr == "" {
6863
return nil, fmt.Errorf("plugin_local_addr is required")
6964
}
@@ -96,7 +91,16 @@ func NewHTTPS2HTTPPlugin(params map[string]string) (Plugin, error) {
9691
Handler: rp,
9792
}
9893

99-
tlsConfig, err := p.genTLSConfig()
94+
var (
95+
tlsConfig *tls.Config
96+
err error
97+
)
98+
if crtPath != "" || keyPath != "" {
99+
tlsConfig, err = p.genTLSConfig()
100+
} else {
101+
tlsConfig, err = transport.NewServerTLSConfig("", "", "")
102+
tlsConfig.InsecureSkipVerify = true
103+
}
100104
if err != nil {
101105
return nil, fmt.Errorf("gen TLS config error: %v", err)
102106
}

0 commit comments

Comments
 (0)