Add basic auth to dashboard

This commit is contained in:
Eric Larssen 2016-08-13 09:32:11 -05:00 committed by Damon Zhao
parent b403e4142b
commit 4dadaac905
5 changed files with 86 additions and 23 deletions

View File

@ -6,7 +6,7 @@
## What is frp?
frp is a fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.Now, it supports tcp, http and https protocol when requests can be forwarded by domains to backward web services.
frp is a fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet. Now, it supports tcp, http and https protocol when requests can be forwarded by domains to backward web services.
## Catalog
@ -37,9 +37,9 @@ frp is a fast reverse proxy to help you expose a local server behind a NAT or fi
## Status
frp is under development and you can try it with latest release version.Master branch for releasing stable version when dev branch for developing.
frp is under development and you can try it with latest release version. Master branch for releasing stable version when dev branch for developing.
**We may change any protocol and can't promise backward compatible.Please check the release log when upgrading.**
**We may change any protocol and can't promise backward compatible. Please check the release log when upgrading.**
## Architecture
@ -149,9 +149,12 @@ Configure a port for dashboard to enable this feature:
```ini
[common]
dashboard_port = 7500
# dashboard's username and password are both optionalif not set, default is admin.
dashboard_username = abc
dashboard_password = abc
```
Then visit `http://[server_addr]:7500` to see dashboard.
Then visit `http://[server_addr]:7500` to see dashboard, default username and password are both `admin`.
![dashboard](/doc/pic/dashboard.png)

View File

@ -146,9 +146,12 @@ frp 目前正在前期开发阶段master 分支用于发布稳定版本dev
```ini
[common]
dashboard_port = 7500
# dashboard 用户名密码可选,默认都为 admin
dashboard_username = abc
dashboard_password = abc
```
打开浏览器通过 `http://[server_addr]:7500` 访问 dashboard 界面。
打开浏览器通过 `http://[server_addr]:7500` 访问 dashboard 界面,用户名密码默认为 `admin`
![dashboard](/doc/pic/dashboard.png)

View File

@ -9,6 +9,9 @@ vhost_http_port = 80
vhost_https_port = 443
# if you want to configure or reload frps by dashboard, dashboard_port must be set
dashboard_port = 7500
# dashboard username and password for basic protect, if not set, both default value is admin
dashboard_username = abc
dashboard_password = abc
# dashboard assets directory(only for debug mode)
# assets_dir = ./static
# console or real logFile path like ./frps.log

View File

@ -30,19 +30,21 @@ import (
// common config
var (
ConfigFile string = "./frps.ini"
BindAddr string = "0.0.0.0"
BindPort int64 = 7000
VhostHttpPort int64 = 0 // if VhostHttpPort equals 0, don't listen a public port for http protocol
VhostHttpsPort int64 = 0 // if VhostHttpsPort equals 0, don't listen a public port for https protocol
DashboardPort int64 = 0 // if DashboardPort equals 0, dashboard is not available
AssetsDir string = ""
LogFile string = "console"
LogWay string = "console" // console or file
LogLevel string = "info"
LogMaxDays int64 = 3
PrivilegeMode bool = false
PrivilegeToken string = ""
ConfigFile string = "./frps.ini"
BindAddr string = "0.0.0.0"
BindPort int64 = 7000
VhostHttpPort int64 = 0 // if VhostHttpPort equals 0, don't listen a public port for http protocol
VhostHttpsPort int64 = 0 // if VhostHttpsPort equals 0, don't listen a public port for https protocol
DashboardPort int64 = 0 // if DashboardPort equals 0, dashboard is not available
DashboardUsername string = "admin"
DashboardPassword string = "admin"
AssetsDir string = ""
LogFile string = "console"
LogWay string = "console" // console or file
LogLevel string = "info"
LogMaxDays int64 = 3
PrivilegeMode bool = false
PrivilegeToken string = ""
// if PrivilegeAllowPorts is not nil, tcp proxies which remote port exist in this map can be connected
PrivilegeAllowPorts map[int64]struct{}
@ -119,6 +121,16 @@ func loadCommonConf(confFile string) error {
DashboardPort = 0
}
tmpStr, ok = conf.Get("common", "dashboard_username")
if ok {
DashboardUsername = tmpStr
}
tmpStr, ok = conf.Get("common", "dashboard_password")
if ok {
DashboardPassword = tmpStr
}
tmpStr, ok = conf.Get("common", "assets_dir")
if ok {
AssetsDir = tmpStr

View File

@ -15,9 +15,11 @@
package server
import (
"encoding/base64"
"fmt"
"net"
"net/http"
"strings"
"time"
"github.com/fatedier/frp/src/assets"
@ -38,7 +40,7 @@ func RunDashboardServer(addr string, port int64) (err error) {
// view, see dashboard_view.go
mux.Handle("/favicon.ico", http.FileServer(assets.FileSystem))
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(assets.FileSystem)))
mux.HandleFunc("/", viewDashboard)
mux.HandleFunc("/", use(viewDashboard, basicAuth))
address := fmt.Sprintf("%s:%d", addr, port)
server := &http.Server{
@ -58,3 +60,43 @@ func RunDashboardServer(addr string, port int64) (err error) {
go server.Serve(ln)
return
}
func use(h http.HandlerFunc, middleware ...func(http.HandlerFunc) http.HandlerFunc) http.HandlerFunc {
for _, m := range middleware {
h = m(h)
}
return h
}
func basicAuth(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
s := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
if len(s) != 2 {
http.Error(w, "Not authorized", 401)
return
}
b, err := base64.StdEncoding.DecodeString(s[1])
if err != nil {
http.Error(w, err.Error(), 401)
return
}
pair := strings.SplitN(string(b), ":", 2)
if len(pair) != 2 {
http.Error(w, "Not authorized", 401)
return
}
if pair[0] != DashboardUsername || pair[1] != DashboardPassword {
http.Error(w, "Not authorized", 401)
return
}
h.ServeHTTP(w, r)
}
}