Fix speed limit

This commit is contained in:
kasuganosoras 2019-09-09 12:57:40 +08:00
parent fb65a33047
commit f60fbde9ee
7 changed files with 74 additions and 43 deletions

View File

@ -150,10 +150,10 @@ func (s Service) CheckProxy(user string, pMsg *msg.NewProxy, timestamp int64, st
func (s Service) GetProxyLimit(user string, pxyConf *config.BaseProxyConf, timestamp int64, stk string) (inLimit, outLimit uint64, err error) { func (s Service) GetProxyLimit(user string, pxyConf *config.BaseProxyConf, timestamp int64, stk string) (inLimit, outLimit uint64, err error) {
// 这部分就照之前的搬过去了能跑就行x // 这部分就照之前的搬过去了能跑就行x
values := url.Values{} values := url.Values{}
values.Set("do", "getlimit") values.Set("action", "getlimit")
values.Set("user", user) values.Set("user", user)
values.Set("timestamp", fmt.Sprintf("%d", timestamp)) values.Set("timestamp", fmt.Sprintf("%d", timestamp))
values.Set("frpstoken", stk) values.Set("apitoken", stk)
s.Host.RawQuery = values.Encode() s.Host.RawQuery = values.Encode()
defer func(u *url.URL) { defer func(u *url.URL) {
u.RawQuery = "" u.RawQuery = ""
@ -180,6 +180,8 @@ func (s Service) GetProxyLimit(user string, pxyConf *config.BaseProxyConf, times
if err = json.Unmarshal(body, response); err != nil { if err = json.Unmarshal(body, response); err != nil {
return 0, 0, err return 0, 0, err
} }
// 这里直接返回 uint64 应该问题不大
return response.MaxIn, response.MaxOut, nil return response.MaxIn, response.MaxOut, nil
} }
@ -193,11 +195,11 @@ func BoolToString(val bool) (str string) {
type ErrHTTPStatus struct { type ErrHTTPStatus struct {
Status int `json:"status"` Status int `json:"status"`
Text string `json:"massage"` Text string `json:"message"`
} }
func (e ErrHTTPStatus) Error() string { func (e ErrHTTPStatus) Error() string {
return fmt.Sprintf("%s", e.Text) return fmt.Sprintf("SakuraFrp API Error (Status: %d, Text: %s)", e.Status, e.Text)
} }
type ResponseGetLimit struct { type ResponseGetLimit struct {

6
extend/limit/limit.go Normal file → Executable file
View File

@ -26,9 +26,11 @@ type LimitConn struct {
} }
func NewLimitConn(maxread, maxwrite uint64, c frpNet.Conn) LimitConn { func NewLimitConn(maxread, maxwrite uint64, c frpNet.Conn) LimitConn {
// 这里不知道为什么要 49 才能对的上真实速度
// 49 是根据 wget 速度来取的,测试了 512、1024、2048、4096、8192 等多种速度下都很准确
return LimitConn{ return LimitConn{
lr: NewReaderWithLimit(c, maxread*KB), lr: NewReaderWithLimit(c, maxread * 49),
lw: NewWriterWithLimit(c, maxwrite*KB), lw: NewWriterWithLimit(c, maxwrite * 49),
Conn: c, Conn: c,
} }
} }

View File

@ -69,7 +69,7 @@ type ServerCommonConf struct {
Token string `json:"token"` Token string `json:"token"`
SubDomainHost string `json:"subdomain_host"` SubDomainHost string `json:"subdomain_host"`
TcpMux bool `json:"tcp_mux"` TcpMux bool `json:"tcp_mux"`
Custom404Page string `json:"custom_404_page"` Custom503Page string `json:"custom_503_page"`
AllowPorts map[int]struct{} AllowPorts map[int]struct{}
MaxPoolCount int64 `json:"max_pool_count"` MaxPoolCount int64 `json:"max_pool_count"`
@ -110,7 +110,7 @@ func GetDefaultServerConf() *ServerCommonConf {
MaxPortsPerClient: 0, MaxPortsPerClient: 0,
HeartBeatTimeout: 90, HeartBeatTimeout: 90,
UserConnTimeout: 10, UserConnTimeout: 10,
Custom404Page: "", Custom503Page: "",
EnableApi: false, EnableApi: false,
ApiBaseUrl: "", ApiBaseUrl: "",
ApiToken: "", ApiToken: "",
@ -303,8 +303,8 @@ func UnmarshalServerConfFromIni(defaultCfg *ServerCommonConf, content string) (c
cfg.TcpMux = true cfg.TcpMux = true
} }
if tmpStr, ok = conf.Get("common", "custom_404_page"); ok { if tmpStr, ok = conf.Get("common", "custom_503_page"); ok {
cfg.Custom404Page = tmpStr cfg.Custom503Page = tmpStr
} }
if tmpStr, ok = conf.Get("common", "heartbeat_timeout"); ok { if tmpStr, ok = conf.Get("common", "heartbeat_timeout"); ok {

View File

@ -431,7 +431,7 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err
// Load configures from NewProxy message and check. // Load configures from NewProxy message and check.
pxyConf, err = config.NewProxyConfFromMsg(pxyMsg) pxyConf, err = config.NewProxyConfFromMsg(pxyMsg)
if err != nil { if err != nil {
return return remoteAddr, err
} }
if g.GlbServerCfg.EnableApi { if g.GlbServerCfg.EnableApi {
@ -451,6 +451,10 @@ func (ctl *Control) RegisterProxy(pxyMsg *msg.NewProxy) (remoteAddr string, err
if err != nil { if err != nil {
return remoteAddr, err return remoteAddr, err
} }
// 测试用
ctl.conn.Debug("client speed limit: %dKB/s (Inbound) / %dKB/s (Outbound)", in, out)
workConn = func() (frpNet.Conn, error) { workConn = func() (frpNet.Conn, error) {
fconn, err := ctl.GetWorkConn() fconn, err := ctl.GetWorkConn()
if err != nil { if err != nil {

View File

@ -119,7 +119,7 @@ func NewService() (svr *Service, err error) {
} }
// Init 404 not found page // Init 404 not found page
vhost.NotFoundPagePath = cfg.Custom404Page vhost.ServiceUnavailablePagePath = cfg.Custom503Page
var ( var (
httpMuxOn bool httpMuxOn bool

4
utils/vhost/http.go Normal file → Executable file
View File

@ -93,8 +93,8 @@ func NewHttpReverseProxy(option HttpReverseProxyOptions, vhostRouter *VhostRoute
ErrorLog: log.New(newWrapLogger(), "", 0), ErrorLog: log.New(newWrapLogger(), "", 0),
ErrorHandler: func(rw http.ResponseWriter, req *http.Request, err error) { ErrorHandler: func(rw http.ResponseWriter, req *http.Request, err error) {
frpLog.Warn("do http proxy request error: %v", err) frpLog.Warn("do http proxy request error: %v", err)
rw.WriteHeader(http.StatusNotFound) rw.WriteHeader(http.StatusServiceUnavailable)
rw.Write(getNotFoundPageContent()) rw.Write(getServiceUnavailablePageContent())
}, },
} }
rp.proxy = proxy rp.proxy = proxy

71
utils/vhost/resource.go Normal file → Executable file
View File

@ -24,63 +24,86 @@ import (
) )
var ( var (
NotFoundPagePath = "" ServiceUnavailablePagePath = ""
) )
const ( const (
NotFound = `<!DOCTYPE html> ServiceUnavailable = `<!DOCTYPE html>
<html> <html>
<head> <head>
<title>Not Found</title> <title>503 Service Unavailable</title>
<style> <style>
body { body {
background: #F1F1F1;
}
.box {
width: 35em; width: 35em;
margin: 0 auto; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; font-family: Tahoma, Verdana, Arial, sans-serif;
background: #FFF;
padding: 8px 32px;
box-shadow: 0px 0px 16px rgba(0,0,0,0.1);
margin-top: 80px;
font-weight: 300;
} }
</style> .box h1 {
</head> font-weight: 300;
<body> }
<h1>The page you visit not found.</h1> </style>
<p>Sorry, the page you are looking for is currently unavailable.<br/> </head>
Please try again later.</p> <body>
<p>The server is powered by <a href="https://github.com/fatedier/frp">frp</a>.</p> <div class="box">
<p><em>Faithfully yours, frp.</em></p> <h1>503 Service Unavailable</h1>
</body> <p>您访问的网站或服务暂时不可用</p>
<p>如果您是隧道所有者造成无法访问的原因可能有</p>
<ul>
<li>您访问的网站使用了内网穿透但是对应的客户端没有运行</li>
<li>该网站或隧道已被管理员临时或永久禁止连接</li>
<li>域名解析更改还未生效或解析错误请检查设置是否正确</li>
</ul>
<p>如果您是普通访问者您可以</p>
<ul>
<li>稍等一段时间后再次尝试访问此站点</li>
<li>尝试与该网站的所有者取得联系</li>
<li>刷新您的 DNS 缓存或在其他网络环境访问</li>
</ul>
<p align="right"><em>Powered by Sakura Panel | Based on Frp</em></p>
</div>
</body>
</html> </html>
` `
) )
func getNotFoundPageContent() []byte { func getServiceUnavailablePageContent() []byte {
var ( var (
buf []byte buf []byte
err error err error
) )
if NotFoundPagePath != "" { if ServiceUnavailablePagePath != "" {
buf, err = ioutil.ReadFile(NotFoundPagePath) buf, err = ioutil.ReadFile(ServiceUnavailablePagePath)
if err != nil { if err != nil {
frpLog.Warn("read custom 404 page error: %v", err) frpLog.Warn("read custom 503 page error: %v", err)
buf = []byte(NotFound) buf = []byte(ServiceUnavailable)
} }
} else { } else {
buf = []byte(NotFound) buf = []byte(ServiceUnavailable)
} }
return buf return buf
} }
func notFoundResponse() *http.Response { func notFoundResponse() *http.Response {
header := make(http.Header) header := make(http.Header)
header.Set("server", "frp/"+version.Full()) header.Set("server", "frp/" + version.Full() + "-sakurapanel")
header.Set("Content-Type", "text/html") header.Set("Content-Type", "text/html")
res := &http.Response{ res := &http.Response{
Status: "Not Found", Status: "Service Unavailable",
StatusCode: 404, StatusCode: 503,
Proto: "HTTP/1.0", Proto: "HTTP/1.0",
ProtoMajor: 1, ProtoMajor: 1,
ProtoMinor: 0, ProtoMinor: 0,
Header: header, Header: header,
Body: ioutil.NopCloser(bytes.NewReader(getNotFoundPageContent())), Body: ioutil.NopCloser(bytes.NewReader(getServiceUnavailablePageContent())),
} }
return res return res
} }