mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-04 22:57:20 +02:00
3.0.1 init commit
- Removed Go HTTP client UA - Added optional bypass of websocket origin check #107 - Added basic forward proxy for debug - Fixed UI error in network utils tab
This commit is contained in:
parent
9b2168466c
commit
200c924acd
@ -4,7 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
strip "github.com/grokify/html-strip-tags-go"
|
"github.com/microcosm-cc/bluemonday"
|
||||||
"imuslab.com/zoraxy/mod/geodb"
|
"imuslab.com/zoraxy/mod/geodb"
|
||||||
"imuslab.com/zoraxy/mod/utils"
|
"imuslab.com/zoraxy/mod/utils"
|
||||||
)
|
)
|
||||||
@ -137,7 +137,8 @@ func handleCountryWhitelistAdd(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
comment, _ := utils.PostPara(r, "comment")
|
comment, _ := utils.PostPara(r, "comment")
|
||||||
comment = strip.StripTags(comment)
|
p := bluemonday.StrictPolicy()
|
||||||
|
comment = p.Sanitize(comment)
|
||||||
|
|
||||||
geodbStore.AddCountryCodeToWhitelist(countryCode, comment)
|
geodbStore.AddCountryCodeToWhitelist(countryCode, comment)
|
||||||
|
|
||||||
@ -164,7 +165,8 @@ func handleIpWhitelistAdd(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
comment, _ := utils.PostPara(r, "comment")
|
comment, _ := utils.PostPara(r, "comment")
|
||||||
comment = strip.StripTags(comment)
|
p := bluemonday.StrictPolicy()
|
||||||
|
comment = p.Sanitize(comment)
|
||||||
|
|
||||||
geodbStore.AddIPToWhiteList(ipAddr, comment)
|
geodbStore.AddIPToWhiteList(ipAddr, comment)
|
||||||
}
|
}
|
||||||
|
@ -163,6 +163,8 @@ func initAPIs() {
|
|||||||
authRouter.HandleFunc("/api/tools/smtp/set", HandleSMTPSet)
|
authRouter.HandleFunc("/api/tools/smtp/set", HandleSMTPSet)
|
||||||
authRouter.HandleFunc("/api/tools/smtp/admin", HandleAdminEmailGet)
|
authRouter.HandleFunc("/api/tools/smtp/admin", HandleAdminEmailGet)
|
||||||
authRouter.HandleFunc("/api/tools/smtp/test", HandleTestEmailSend)
|
authRouter.HandleFunc("/api/tools/smtp/test", HandleTestEmailSend)
|
||||||
|
authRouter.HandleFunc("/api/tools/fwdproxy/enable", forwardProxy.HandleToogle)
|
||||||
|
authRouter.HandleFunc("/api/tools/fwdproxy/port", forwardProxy.HandlePort)
|
||||||
|
|
||||||
//Account Reset
|
//Account Reset
|
||||||
http.HandleFunc("/api/account/reset", HandleAdminAccountResetEmail)
|
http.HandleFunc("/api/account/reset", HandleAdminAccountResetEmail)
|
||||||
|
@ -10,11 +10,10 @@ require (
|
|||||||
github.com/gorilla/sessions v1.2.1
|
github.com/gorilla/sessions v1.2.1
|
||||||
github.com/gorilla/websocket v1.5.0
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/grandcat/zeroconf v1.0.0
|
github.com/grandcat/zeroconf v1.0.0
|
||||||
github.com/grokify/html-strip-tags-go v0.1.0
|
|
||||||
github.com/likexian/whois v1.15.1
|
github.com/likexian/whois v1.15.1
|
||||||
github.com/microcosm-cc/bluemonday v1.0.25
|
github.com/microcosm-cc/bluemonday v1.0.25
|
||||||
golang.org/x/net v0.14.0
|
golang.org/x/net v0.20.0
|
||||||
golang.org/x/sys v0.11.0
|
golang.org/x/sys v0.16.0
|
||||||
golang.org/x/text v0.12.0
|
golang.org/x/text v0.14.0
|
||||||
golang.org/x/tools v0.12.0 // indirect
|
golang.org/x/tools v0.12.0 // indirect
|
||||||
)
|
)
|
||||||
|
15
src/go.sum
15
src/go.sum
@ -740,8 +740,6 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
|
|||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE=
|
github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE=
|
||||||
github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfcP2PdzytEs=
|
github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfcP2PdzytEs=
|
||||||
github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4=
|
|
||||||
github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc=
|
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
@ -1146,8 +1144,9 @@ golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE
|
|||||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||||
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
|
||||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||||
|
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||||
|
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@ -1268,8 +1267,9 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
|||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||||
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
|
||||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||||
|
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||||
|
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@ -1421,8 +1421,9 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
|
|
||||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||||
|
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
@ -1437,6 +1438,7 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
|||||||
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
|
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
|
||||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||||
|
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@ -1455,8 +1457,9 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
|
|
||||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"imuslab.com/zoraxy/mod/database"
|
"imuslab.com/zoraxy/mod/database"
|
||||||
"imuslab.com/zoraxy/mod/dynamicproxy/redirection"
|
"imuslab.com/zoraxy/mod/dynamicproxy/redirection"
|
||||||
"imuslab.com/zoraxy/mod/email"
|
"imuslab.com/zoraxy/mod/email"
|
||||||
|
"imuslab.com/zoraxy/mod/forwardproxy"
|
||||||
"imuslab.com/zoraxy/mod/ganserv"
|
"imuslab.com/zoraxy/mod/ganserv"
|
||||||
"imuslab.com/zoraxy/mod/geodb"
|
"imuslab.com/zoraxy/mod/geodb"
|
||||||
"imuslab.com/zoraxy/mod/info/logger"
|
"imuslab.com/zoraxy/mod/info/logger"
|
||||||
@ -49,9 +50,9 @@ var logOutputToFile = flag.Bool("log", true, "Log terminal output to file")
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
name = "Zoraxy"
|
name = "Zoraxy"
|
||||||
version = "3.0.0"
|
version = "3.0.1"
|
||||||
nodeUUID = "generic"
|
nodeUUID = "generic"
|
||||||
development = false //Set this to false to use embedded web fs
|
development = true //Set this to false to use embedded web fs
|
||||||
bootTime = time.Now().Unix()
|
bootTime = time.Now().Unix()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -79,6 +80,7 @@ var (
|
|||||||
acmeHandler *acme.ACMEHandler //Handler for ACME Certificate renew
|
acmeHandler *acme.ACMEHandler //Handler for ACME Certificate renew
|
||||||
acmeAutoRenewer *acme.AutoRenewer //Handler for ACME auto renew ticking
|
acmeAutoRenewer *acme.AutoRenewer //Handler for ACME auto renew ticking
|
||||||
staticWebServer *webserv.WebServer //Static web server for hosting simple stuffs
|
staticWebServer *webserv.WebServer //Static web server for hosting simple stuffs
|
||||||
|
forwardProxy *forwardproxy.Handler //HTTP Forward proxy, basically VPN for web browser
|
||||||
|
|
||||||
//Helper modules
|
//Helper modules
|
||||||
EmailSender *email.Sender //Email sender that handle email sending
|
EmailSender *email.Sender //Email sender that handle email sending
|
||||||
|
@ -272,6 +272,14 @@ func removeHeaders(header http.Header, noCache bool) {
|
|||||||
header.Del("Cache-Control")
|
header.Del("Cache-Control")
|
||||||
header.Set("Cache-Control", "no-store")
|
header.Set("Cache-Control", "no-store")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Hide Go-HTTP-Client UA if the client didnt sent us one
|
||||||
|
if _, ok := header["User-Agent"]; !ok {
|
||||||
|
// If the outbound request doesn't have a User-Agent header set,
|
||||||
|
// don't send the default Go HTTP client User-Agent.
|
||||||
|
header.Set("User-Agent", "")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func addXForwardedForHeader(req *http.Request) {
|
func addXForwardedForHeader(req *http.Request) {
|
||||||
@ -365,6 +373,12 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if res.StatusCode == 501 || res.StatusCode == 500 {
|
||||||
|
// fmt.Println(outreq.Proto, outreq.RemoteAddr, outreq.RequestURI)
|
||||||
|
// fmt.Println(">>>", outreq.Method, res.Header, res.ContentLength, res.StatusCode)
|
||||||
|
// fmt.Println(outreq.Header, req.Host)
|
||||||
|
//}
|
||||||
|
|
||||||
//Custom header rewriter functions
|
//Custom header rewriter functions
|
||||||
if res.Header.Get("Location") != "" {
|
if res.Header.Get("Location") != "" {
|
||||||
locationRewrite := res.Header.Get("Location")
|
locationRewrite := res.Header.Get("Location")
|
||||||
|
@ -114,7 +114,10 @@ func (h *ProxyHandler) hostRequest(w http.ResponseWriter, r *http.Request, targe
|
|||||||
u, _ = url.Parse("wss://" + wsRedirectionEndpoint + requestURL)
|
u, _ = url.Parse("wss://" + wsRedirectionEndpoint + requestURL)
|
||||||
}
|
}
|
||||||
h.logRequest(r, true, 101, "subdomain-websocket", target.Domain)
|
h.logRequest(r, true, 101, "subdomain-websocket", target.Domain)
|
||||||
wspHandler := websocketproxy.NewProxy(u, target.SkipCertValidations)
|
wspHandler := websocketproxy.NewProxy(u, websocketproxy.Options{
|
||||||
|
SkipTLSValidation: target.SkipCertValidations,
|
||||||
|
SkipOriginCheck: target.SkipWebSocketOriginCheck,
|
||||||
|
})
|
||||||
wspHandler.ServeHTTP(w, r)
|
wspHandler.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -178,7 +181,10 @@ func (h *ProxyHandler) vdirRequest(w http.ResponseWriter, r *http.Request, targe
|
|||||||
u, _ = url.Parse("wss://" + wsRedirectionEndpoint + r.URL.String())
|
u, _ = url.Parse("wss://" + wsRedirectionEndpoint + r.URL.String())
|
||||||
}
|
}
|
||||||
h.logRequest(r, true, 101, "vdir-websocket", target.Domain)
|
h.logRequest(r, true, 101, "vdir-websocket", target.Domain)
|
||||||
wspHandler := websocketproxy.NewProxy(u, target.SkipCertValidations)
|
wspHandler := websocketproxy.NewProxy(u, websocketproxy.Options{
|
||||||
|
SkipTLSValidation: target.SkipCertValidations,
|
||||||
|
SkipOriginCheck: target.parent.SkipWebSocketOriginCheck,
|
||||||
|
})
|
||||||
wspHandler.ServeHTTP(w, r)
|
wspHandler.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -95,9 +95,10 @@ type ProxyEndpoint struct {
|
|||||||
Domain string //Domain or IP to proxy to
|
Domain string //Domain or IP to proxy to
|
||||||
|
|
||||||
//TLS/SSL Related
|
//TLS/SSL Related
|
||||||
RequireTLS bool //Target domain require TLS
|
RequireTLS bool //Target domain require TLS
|
||||||
BypassGlobalTLS bool //Bypass global TLS setting options if TLS Listener enabled (parent.tlsListener != nil)
|
BypassGlobalTLS bool //Bypass global TLS setting options if TLS Listener enabled (parent.tlsListener != nil)
|
||||||
SkipCertValidations bool //Set to true to accept self signed certs
|
SkipCertValidations bool //Set to true to accept self signed certs
|
||||||
|
SkipWebSocketOriginCheck bool //Skip origin check on websocket upgrade connections
|
||||||
|
|
||||||
//Virtual Directories
|
//Virtual Directories
|
||||||
VirtualDirectories []*VirtualDirectoryEndpoint
|
VirtualDirectories []*VirtualDirectoryEndpoint
|
||||||
@ -115,6 +116,7 @@ type ProxyEndpoint struct {
|
|||||||
DefaultSiteValue string //Fallback routing target, optional
|
DefaultSiteValue string //Fallback routing target, optional
|
||||||
|
|
||||||
Disabled bool //If the rule is disabled
|
Disabled bool //If the rule is disabled
|
||||||
|
|
||||||
//Internal Logic Elements
|
//Internal Logic Elements
|
||||||
parent *Router
|
parent *Router
|
||||||
proxy *dpcore.ReverseProxy `json:"-"`
|
proxy *dpcore.ReverseProxy `json:"-"`
|
||||||
|
25
src/mod/forwardproxy/cproxy/LICENSE.md
Normal file
25
src/mod/forwardproxy/cproxy/LICENSE.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2022 Smarty
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
NOTE: Various optional and subordinate components carry their own licensing
|
||||||
|
requirements and restrictions. Use of those components is subject to the terms
|
||||||
|
and conditions outlined the respective license of each component.
|
109
src/mod/forwardproxy/cproxy/config.go
Normal file
109
src/mod/forwardproxy/cproxy/config.go
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
package cproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(options ...option) http.Handler {
|
||||||
|
var this configuration
|
||||||
|
Options.apply(options...)(&this)
|
||||||
|
return newHandler(this.Filter, this.ClientConnector, this.ServerConnector, this.Monitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
var Options singleton
|
||||||
|
|
||||||
|
type singleton struct{}
|
||||||
|
type option func(*configuration)
|
||||||
|
|
||||||
|
type configuration struct {
|
||||||
|
DialTimeout time.Duration
|
||||||
|
Filter Filter
|
||||||
|
DialAddress string
|
||||||
|
Dialer Dialer
|
||||||
|
LogConnections bool
|
||||||
|
ProxyProtocol bool
|
||||||
|
Initializer initializer
|
||||||
|
ClientConnector clientConnector
|
||||||
|
ServerConnector serverConnector
|
||||||
|
Monitor monitor
|
||||||
|
Logger logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func (singleton) DialTimeout(value time.Duration) option {
|
||||||
|
return func(this *configuration) { this.DialTimeout = value }
|
||||||
|
}
|
||||||
|
func (singleton) Filter(value Filter) option {
|
||||||
|
return func(this *configuration) { this.Filter = value }
|
||||||
|
}
|
||||||
|
func (singleton) ClientConnector(value clientConnector) option {
|
||||||
|
return func(this *configuration) { this.ClientConnector = value }
|
||||||
|
}
|
||||||
|
func (singleton) DialAddress(value string) option {
|
||||||
|
return func(this *configuration) { this.DialAddress = value }
|
||||||
|
}
|
||||||
|
func (singleton) Dialer(value Dialer) option {
|
||||||
|
return func(this *configuration) { this.Dialer = value }
|
||||||
|
}
|
||||||
|
func (singleton) LogConnections(value bool) option {
|
||||||
|
return func(this *configuration) { this.LogConnections = value }
|
||||||
|
}
|
||||||
|
func (singleton) ProxyProtocol(value bool) option {
|
||||||
|
return func(this *configuration) { this.ProxyProtocol = value }
|
||||||
|
}
|
||||||
|
func (singleton) Initializer(value initializer) option {
|
||||||
|
return func(this *configuration) { this.Initializer = value }
|
||||||
|
}
|
||||||
|
func (singleton) ServerConnector(value serverConnector) option {
|
||||||
|
return func(this *configuration) { this.ServerConnector = value }
|
||||||
|
}
|
||||||
|
func (singleton) Monitor(value monitor) option {
|
||||||
|
return func(this *configuration) { this.Monitor = value }
|
||||||
|
}
|
||||||
|
func (singleton) Logger(value logger) option {
|
||||||
|
return func(this *configuration) { this.Logger = value }
|
||||||
|
}
|
||||||
|
|
||||||
|
func (singleton) apply(options ...option) option {
|
||||||
|
return func(this *configuration) {
|
||||||
|
for _, item := range Options.defaults(options...) {
|
||||||
|
item(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
if this.Dialer == nil {
|
||||||
|
this.Dialer = newDialer(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Dialer = newRoutingDialer(this)
|
||||||
|
|
||||||
|
if this.ProxyProtocol {
|
||||||
|
this.Initializer = newProxyProtocolInitializer()
|
||||||
|
}
|
||||||
|
|
||||||
|
if this.Initializer == nil {
|
||||||
|
this.Initializer = nop{}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Initializer = newLoggingInitializer(this)
|
||||||
|
|
||||||
|
if this.ServerConnector == nil {
|
||||||
|
this.ServerConnector = newServerConnector(this.Dialer, this.Initializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (singleton) defaults(options ...option) []option {
|
||||||
|
return append([]option{
|
||||||
|
Options.DialTimeout(time.Second * 10),
|
||||||
|
Options.Filter(newFilter()),
|
||||||
|
Options.ClientConnector(newClientConnector()),
|
||||||
|
Options.Initializer(nop{}),
|
||||||
|
Options.Monitor(nop{}),
|
||||||
|
Options.Logger(nop{}),
|
||||||
|
}, options...)
|
||||||
|
}
|
||||||
|
|
||||||
|
type nop struct{}
|
||||||
|
|
||||||
|
func (nop) Measure(int) {}
|
||||||
|
func (nop) Printf(string, ...interface{}) {}
|
||||||
|
func (nop) Initialize(Socket, Socket) bool { return true }
|
19
src/mod/forwardproxy/cproxy/default_client_connector.go
Normal file
19
src/mod/forwardproxy/cproxy/default_client_connector.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package cproxy
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type defaultClientConnector struct{}
|
||||||
|
|
||||||
|
func newClientConnector() *defaultClientConnector {
|
||||||
|
return &defaultClientConnector{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *defaultClientConnector) Connect(response http.ResponseWriter) Socket {
|
||||||
|
if hijacker, ok := response.(http.Hijacker); !ok {
|
||||||
|
return nil
|
||||||
|
} else if socket, _, _ := hijacker.Hijack(); socket == nil {
|
||||||
|
return nil // this 'else if' exists to avoid the pointer nil != interface nil issue
|
||||||
|
} else {
|
||||||
|
return socket
|
||||||
|
}
|
||||||
|
}
|
25
src/mod/forwardproxy/cproxy/default_dialer.go
Normal file
25
src/mod/forwardproxy/cproxy/default_dialer.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package cproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type defaultDialer struct {
|
||||||
|
timeout time.Duration
|
||||||
|
logger logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDialer(config *configuration) *defaultDialer {
|
||||||
|
return &defaultDialer{timeout: config.DialTimeout, logger: config.Logger}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *defaultDialer) Dial(address string) Socket {
|
||||||
|
if socket, err := net.DialTimeout("tcp", address, this.timeout); err == nil {
|
||||||
|
return socket
|
||||||
|
} else {
|
||||||
|
this.logger.Printf("[INFO] Unable to establish connection to [%s]: %s", address, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
9
src/mod/forwardproxy/cproxy/default_filter.go
Normal file
9
src/mod/forwardproxy/cproxy/default_filter.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package cproxy
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type defaultFilter struct{}
|
||||||
|
|
||||||
|
func newFilter() *defaultFilter { return &defaultFilter{} }
|
||||||
|
|
||||||
|
func (this *defaultFilter) IsAuthorized(http.ResponseWriter, *http.Request) bool { return true }
|
56
src/mod/forwardproxy/cproxy/default_handler.go
Normal file
56
src/mod/forwardproxy/cproxy/default_handler.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package cproxy
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type defaultHandler struct {
|
||||||
|
filter Filter
|
||||||
|
clientConnector clientConnector
|
||||||
|
serverConnector serverConnector
|
||||||
|
meter monitor
|
||||||
|
}
|
||||||
|
|
||||||
|
func newHandler(filter Filter, clientConnector clientConnector, serverConnector serverConnector, meter monitor) *defaultHandler {
|
||||||
|
return &defaultHandler{
|
||||||
|
filter: filter,
|
||||||
|
clientConnector: clientConnector,
|
||||||
|
serverConnector: serverConnector,
|
||||||
|
meter: meter,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *defaultHandler) ServeHTTP(response http.ResponseWriter, request *http.Request) {
|
||||||
|
this.meter.Measure(MeasurementHTTPRequest)
|
||||||
|
|
||||||
|
if request.Method != "CONNECT" {
|
||||||
|
this.meter.Measure(MeasurementBadMethod)
|
||||||
|
writeResponseStatus(response, http.StatusMethodNotAllowed)
|
||||||
|
|
||||||
|
} else if !this.filter.IsAuthorized(response, request) {
|
||||||
|
this.meter.Measure(MeasurementUnauthorizedRequest)
|
||||||
|
//writeResponseStatus(response, http.StatusUnauthorized)
|
||||||
|
|
||||||
|
} else if client := this.clientConnector.Connect(response); client == nil {
|
||||||
|
this.meter.Measure(MeasurementClientConnectionFailed)
|
||||||
|
writeResponseStatus(response, http.StatusNotImplemented)
|
||||||
|
|
||||||
|
} else if connection := this.serverConnector.Connect(client, request.URL.Host); connection == nil {
|
||||||
|
this.meter.Measure(MeasurementServerConnectionFailed)
|
||||||
|
_, _ = client.Write(statusBadGateway)
|
||||||
|
_ = client.Close()
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.meter.Measure(MeasurementProxyReady)
|
||||||
|
_, _ = client.Write(statusReady)
|
||||||
|
connection.Proxy()
|
||||||
|
this.meter.Measure(MeasurementProxyComplete)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeResponseStatus(response http.ResponseWriter, statusCode int) {
|
||||||
|
http.Error(response, http.StatusText(statusCode), statusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
statusBadGateway = []byte("HTTP/1.1 502 Bad Gateway\r\n\r\n")
|
||||||
|
statusReady = []byte("HTTP/1.1 200 OK\r\n\r\n")
|
||||||
|
)
|
54
src/mod/forwardproxy/cproxy/default_proxy.go
Normal file
54
src/mod/forwardproxy/cproxy/default_proxy.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package cproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type defaultProxy struct {
|
||||||
|
client Socket
|
||||||
|
server Socket
|
||||||
|
waiter *sync.WaitGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func newProxy(client, server Socket) *defaultProxy {
|
||||||
|
waiter := &sync.WaitGroup{}
|
||||||
|
waiter.Add(2) // wait on both client->server and server->client streams
|
||||||
|
|
||||||
|
return &defaultProxy{
|
||||||
|
waiter: waiter,
|
||||||
|
client: client,
|
||||||
|
server: server,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *defaultProxy) Proxy() {
|
||||||
|
go this.streamAndClose(this.client, this.server)
|
||||||
|
go this.streamAndClose(this.server, this.client)
|
||||||
|
this.closeSockets()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *defaultProxy) streamAndClose(reader, writer Socket) {
|
||||||
|
_, _ = io.Copy(writer, reader)
|
||||||
|
|
||||||
|
tryCloseRead(reader)
|
||||||
|
tryCloseWrite(writer)
|
||||||
|
|
||||||
|
this.waiter.Done()
|
||||||
|
}
|
||||||
|
func tryCloseRead(socket Socket) {
|
||||||
|
if tcp, ok := socket.(tcpSocket); ok {
|
||||||
|
_ = tcp.CloseRead()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func tryCloseWrite(socket Socket) {
|
||||||
|
if tcp, ok := socket.(tcpSocket); ok {
|
||||||
|
_ = tcp.CloseWrite()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *defaultProxy) closeSockets() {
|
||||||
|
this.waiter.Wait()
|
||||||
|
_ = this.client.Close()
|
||||||
|
_ = this.server.Close()
|
||||||
|
}
|
24
src/mod/forwardproxy/cproxy/default_server_connector.go
Normal file
24
src/mod/forwardproxy/cproxy/default_server_connector.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package cproxy
|
||||||
|
|
||||||
|
type defaultServerConnector struct {
|
||||||
|
dialer Dialer
|
||||||
|
initializer initializer
|
||||||
|
}
|
||||||
|
|
||||||
|
func newServerConnector(dialer Dialer, initializer initializer) *defaultServerConnector {
|
||||||
|
return &defaultServerConnector{dialer: dialer, initializer: initializer}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *defaultServerConnector) Connect(client Socket, serverAddress string) proxy {
|
||||||
|
server := this.dialer.Dial(serverAddress)
|
||||||
|
if server == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !this.initializer.Initialize(client, server) {
|
||||||
|
_ = server.Close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return newProxy(client, server)
|
||||||
|
}
|
32
src/mod/forwardproxy/cproxy/hostname_filter.go
Normal file
32
src/mod/forwardproxy/cproxy/hostname_filter.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package cproxy
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type hostnameFilter struct {
|
||||||
|
authorized []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHostnameFilter(authorized []string) Filter {
|
||||||
|
return &hostnameFilter{authorized: authorized}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this hostnameFilter) IsAuthorized(_ http.ResponseWriter, request *http.Request) bool {
|
||||||
|
if len(this.authorized) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
host := request.URL.Host
|
||||||
|
hostLength := len(host)
|
||||||
|
for _, authorized := range this.authorized {
|
||||||
|
if authorized[:2] == "*." {
|
||||||
|
have, want := hostLength, len(authorized)-1
|
||||||
|
if have > want && authorized[1:] == host[hostLength-want:] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else if authorized == host {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
26
src/mod/forwardproxy/cproxy/hostname_suffix_filter.go
Normal file
26
src/mod/forwardproxy/cproxy/hostname_suffix_filter.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package cproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type hostnameSuffixFilter struct {
|
||||||
|
authorized []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHostnameSuffixFilter(authorized []string) Filter {
|
||||||
|
return &hostnameSuffixFilter{authorized: authorized}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this hostnameSuffixFilter) IsAuthorized(_ http.ResponseWriter, request *http.Request) bool {
|
||||||
|
host := request.URL.Host
|
||||||
|
|
||||||
|
for _, authorized := range this.authorized {
|
||||||
|
if strings.HasSuffix(host, authorized) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
67
src/mod/forwardproxy/cproxy/interfaces.go
Normal file
67
src/mod/forwardproxy/cproxy/interfaces.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package cproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Filter interface {
|
||||||
|
IsAuthorized(http.ResponseWriter, *http.Request) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
clientConnector interface {
|
||||||
|
Connect(http.ResponseWriter) Socket
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Dialer interface {
|
||||||
|
Dial(string) Socket
|
||||||
|
}
|
||||||
|
|
||||||
|
serverConnector interface {
|
||||||
|
Connect(Socket, string) proxy
|
||||||
|
}
|
||||||
|
|
||||||
|
initializer interface {
|
||||||
|
Initialize(Socket, Socket) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy interface {
|
||||||
|
Proxy()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Socket interface {
|
||||||
|
io.ReadWriteCloser
|
||||||
|
RemoteAddr() net.Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
tcpSocket interface {
|
||||||
|
Socket
|
||||||
|
CloseRead() error
|
||||||
|
CloseWrite() error
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
monitor interface {
|
||||||
|
Measure(int)
|
||||||
|
}
|
||||||
|
logger interface {
|
||||||
|
Printf(string, ...interface{})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MeasurementHTTPRequest int = iota
|
||||||
|
MeasurementBadMethod
|
||||||
|
MeasurementUnauthorizedRequest
|
||||||
|
MeasurementClientConnectionFailed
|
||||||
|
MeasurementServerConnectionFailed
|
||||||
|
MeasurementProxyReady
|
||||||
|
MeasurementProxyComplete
|
||||||
|
)
|
24
src/mod/forwardproxy/cproxy/logging_initializer.go
Normal file
24
src/mod/forwardproxy/cproxy/logging_initializer.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package cproxy
|
||||||
|
|
||||||
|
type loggingInitializer struct {
|
||||||
|
logger logger
|
||||||
|
inner initializer
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLoggingInitializer(config *configuration) initializer {
|
||||||
|
if !config.LogConnections {
|
||||||
|
return config.Initializer
|
||||||
|
}
|
||||||
|
|
||||||
|
return &loggingInitializer{inner: config.Initializer, logger: config.Logger}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *loggingInitializer) Initialize(client, server Socket) bool {
|
||||||
|
result := this.inner.Initialize(client, server)
|
||||||
|
|
||||||
|
if !result {
|
||||||
|
this.logger.Printf("[INFO] Connection failed [%s] -> [%s]", client.RemoteAddr(), server.RemoteAddr())
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
36
src/mod/forwardproxy/cproxy/proxy_protocol_initializer.go
Normal file
36
src/mod/forwardproxy/cproxy/proxy_protocol_initializer.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package cproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type proxyProtocolInitializer struct{}
|
||||||
|
|
||||||
|
func newProxyProtocolInitializer() *proxyProtocolInitializer {
|
||||||
|
return &proxyProtocolInitializer{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *proxyProtocolInitializer) Initialize(client, server Socket) bool {
|
||||||
|
header := formatHeader(client.RemoteAddr(), server.RemoteAddr())
|
||||||
|
_, err := io.WriteString(server, header)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
func formatHeader(client, server net.Addr) string {
|
||||||
|
clientAddress, clientPort := parseAddress(client.String())
|
||||||
|
serverAddress, serverPort := parseAddress(server.String())
|
||||||
|
if strings.Contains(clientAddress, ":") {
|
||||||
|
return fmt.Sprintf(proxyProtocolIPv6Preamble, clientAddress, serverAddress, clientPort, serverPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(proxyProtocolIPv4Preamble, clientAddress, serverAddress, clientPort, serverPort)
|
||||||
|
}
|
||||||
|
func parseAddress(address string) (string, string) {
|
||||||
|
address, port, _ := net.SplitHostPort(address)
|
||||||
|
return address, port
|
||||||
|
}
|
||||||
|
|
||||||
|
const proxyProtocolIPv4Preamble = "PROXY TCP4 %s %s %s %s\r\n"
|
||||||
|
const proxyProtocolIPv6Preamble = "PROXY TCP6 %s %s %s %s\r\n"
|
18
src/mod/forwardproxy/cproxy/routing_dialer.go
Normal file
18
src/mod/forwardproxy/cproxy/routing_dialer.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package cproxy
|
||||||
|
|
||||||
|
type routingDialer struct {
|
||||||
|
inner Dialer
|
||||||
|
targetAddress string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRoutingDialer(config *configuration) Dialer {
|
||||||
|
if len(config.DialAddress) == 0 {
|
||||||
|
return config.Dialer
|
||||||
|
}
|
||||||
|
|
||||||
|
return &routingDialer{inner: config.Dialer, targetAddress: config.DialAddress}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *routingDialer) Dial(string) Socket {
|
||||||
|
return this.inner.Dial(this.targetAddress)
|
||||||
|
}
|
137
src/mod/forwardproxy/forwardproxy.go
Normal file
137
src/mod/forwardproxy/forwardproxy.go
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
package forwardproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"imuslab.com/zoraxy/mod/database"
|
||||||
|
"imuslab.com/zoraxy/mod/forwardproxy/cproxy"
|
||||||
|
"imuslab.com/zoraxy/mod/info/logger"
|
||||||
|
"imuslab.com/zoraxy/mod/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ZrFilter struct {
|
||||||
|
//To be implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
type Handler struct {
|
||||||
|
server *http.Server
|
||||||
|
handler *http.Handler
|
||||||
|
running bool
|
||||||
|
db *database.Database
|
||||||
|
logger *logger.Logger
|
||||||
|
Port int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewForwardProxy(sysdb *database.Database, port int, logger *logger.Logger) *Handler {
|
||||||
|
thisFilter := ZrFilter{}
|
||||||
|
handler := cproxy.New(cproxy.Options.Filter(thisFilter))
|
||||||
|
|
||||||
|
return &Handler{
|
||||||
|
db: sysdb,
|
||||||
|
server: nil,
|
||||||
|
handler: &handler,
|
||||||
|
running: false,
|
||||||
|
logger: logger,
|
||||||
|
Port: port,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the forward proxy
|
||||||
|
func (h *Handler) Start() error {
|
||||||
|
if h.running {
|
||||||
|
return errors.New("forward proxy already running")
|
||||||
|
}
|
||||||
|
server := &http.Server{Addr: ":" + strconv.Itoa(h.Port), Handler: *h.handler}
|
||||||
|
h.server = server
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := server.ListenAndServe(); err != nil {
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
h.running = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the forward proxy
|
||||||
|
func (h *Handler) Stop() error {
|
||||||
|
if h.running && h.server != nil {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
if err := h.server.Shutdown(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
h.running = false
|
||||||
|
h.server = nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the port number of the forward proxy
|
||||||
|
func (h *Handler) UpdatePort(newPort int) error {
|
||||||
|
h.Stop()
|
||||||
|
h.Port = newPort
|
||||||
|
return h.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (it ZrFilter) IsAuthorized(w http.ResponseWriter, r *http.Request) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle port change of the forward proxy
|
||||||
|
func (h *Handler) HandlePort(w http.ResponseWriter, r *http.Request) {
|
||||||
|
port, err := utils.PostInt(r, "port")
|
||||||
|
if err != nil {
|
||||||
|
js, _ := json.Marshal(h.Port)
|
||||||
|
utils.SendJSONResponse(w, string(js))
|
||||||
|
} else {
|
||||||
|
//Update the port
|
||||||
|
err = h.UpdatePort(port)
|
||||||
|
if err != nil {
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.logger.PrintAndLog("Forward Proxy", "HTTP Forward Proxy port updated to :"+strconv.Itoa(h.Port), nil)
|
||||||
|
h.db.Write("fwdproxy", "port", port)
|
||||||
|
utils.SendOK(w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle power toggle of the forward proxys
|
||||||
|
func (h *Handler) HandleToogle(w http.ResponseWriter, r *http.Request) {
|
||||||
|
enabled, err := utils.PostBool(r, "enable")
|
||||||
|
if err != nil {
|
||||||
|
//Get the current state of the forward proxy
|
||||||
|
js, _ := json.Marshal(h.running)
|
||||||
|
utils.SendJSONResponse(w, string(js))
|
||||||
|
} else {
|
||||||
|
if enabled {
|
||||||
|
err = h.Start()
|
||||||
|
if err != nil {
|
||||||
|
h.logger.PrintAndLog("Forward Proxy", "Unable to start forward proxy server", err)
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.logger.PrintAndLog("Forward Proxy", "HTTP Forward Proxy Started, listening on :"+strconv.Itoa(h.Port), nil)
|
||||||
|
} else {
|
||||||
|
err = h.Stop()
|
||||||
|
if err != nil {
|
||||||
|
h.logger.PrintAndLog("Forward Proxy", "Unable to stop forward proxy server", err)
|
||||||
|
utils.SendErrorResponse(w, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.logger.PrintAndLog("Forward Proxy", "HTTP Forward Proxy Stopped", nil)
|
||||||
|
}
|
||||||
|
h.db.Write("fwdproxy", "enabled", enabled)
|
||||||
|
utils.SendOK(w)
|
||||||
|
}
|
||||||
|
}
|
@ -85,7 +85,10 @@ func (m *Manager) HandleHttpByInstanceId(instanceId string, w http.ResponseWrite
|
|||||||
r.Header.Set("Zr-Origin-Upgrade", "websocket")
|
r.Header.Set("Zr-Origin-Upgrade", "websocket")
|
||||||
requestURL = strings.TrimPrefix(requestURL, "/")
|
requestURL = strings.TrimPrefix(requestURL, "/")
|
||||||
u, _ := url.Parse("ws://127.0.0.1:" + strconv.Itoa(targetInstance.AssignedPort) + "/" + requestURL)
|
u, _ := url.Parse("ws://127.0.0.1:" + strconv.Itoa(targetInstance.AssignedPort) + "/" + requestURL)
|
||||||
wspHandler := websocketproxy.NewProxy(u, false)
|
wspHandler := websocketproxy.NewProxy(u, websocketproxy.Options{
|
||||||
|
SkipTLSValidation: false,
|
||||||
|
SkipOriginCheck: false,
|
||||||
|
})
|
||||||
wspHandler.ServeHTTP(w, r)
|
wspHandler.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -47,19 +47,26 @@ type WebsocketProxy struct {
|
|||||||
// If nil, DefaultDialer is used.
|
// If nil, DefaultDialer is used.
|
||||||
Dialer *websocket.Dialer
|
Dialer *websocket.Dialer
|
||||||
|
|
||||||
Verbal bool
|
Verbal bool
|
||||||
SkipTlsValidation bool
|
|
||||||
|
Options Options
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional options for websocket proxy runtime
|
||||||
|
type Options struct {
|
||||||
|
SkipTLSValidation bool //Skip backend TLS validation
|
||||||
|
SkipOriginCheck bool //Skip origin check
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProxyHandler returns a new http.Handler interface that reverse proxies the
|
// ProxyHandler returns a new http.Handler interface that reverse proxies the
|
||||||
// request to the given target.
|
// request to the given target.
|
||||||
func ProxyHandler(target *url.URL, skipTlsValidation bool) http.Handler {
|
func ProxyHandler(target *url.URL, options Options) http.Handler {
|
||||||
return NewProxy(target, skipTlsValidation)
|
return NewProxy(target, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProxy returns a new Websocket reverse proxy that rewrites the
|
// NewProxy returns a new Websocket reverse proxy that rewrites the
|
||||||
// URL's to the scheme, host and base path provider in target.
|
// URL's to the scheme, host and base path provider in target.
|
||||||
func NewProxy(target *url.URL, skipTlsValidation bool) *WebsocketProxy {
|
func NewProxy(target *url.URL, options Options) *WebsocketProxy {
|
||||||
backend := func(r *http.Request) *url.URL {
|
backend := func(r *http.Request) *url.URL {
|
||||||
// Shallow copy
|
// Shallow copy
|
||||||
u := *target
|
u := *target
|
||||||
@ -68,7 +75,7 @@ func NewProxy(target *url.URL, skipTlsValidation bool) *WebsocketProxy {
|
|||||||
u.RawQuery = r.URL.RawQuery
|
u.RawQuery = r.URL.RawQuery
|
||||||
return &u
|
return &u
|
||||||
}
|
}
|
||||||
return &WebsocketProxy{Backend: backend, Verbal: false, SkipTlsValidation: skipTlsValidation}
|
return &WebsocketProxy{Backend: backend, Verbal: false, Options: options}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeHTTP implements the http.Handler that proxies WebSocket connections.
|
// ServeHTTP implements the http.Handler that proxies WebSocket connections.
|
||||||
@ -88,7 +95,7 @@ func (w *WebsocketProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||||||
|
|
||||||
dialer := w.Dialer
|
dialer := w.Dialer
|
||||||
if w.Dialer == nil {
|
if w.Dialer == nil {
|
||||||
if w.SkipTlsValidation {
|
if w.Options.SkipTLSValidation {
|
||||||
//Disable TLS secure check if target allow skip verification
|
//Disable TLS secure check if target allow skip verification
|
||||||
bypassDialer := websocket.DefaultDialer
|
bypassDialer := websocket.DefaultDialer
|
||||||
bypassDialer.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
bypassDialer.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||||
@ -171,6 +178,13 @@ func (w *WebsocketProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|||||||
upgrader = DefaultUpgrader
|
upgrader = DefaultUpgrader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Fixing issue #107 by bypassing request origin check
|
||||||
|
if w.Options.SkipOriginCheck {
|
||||||
|
upgrader.CheckOrigin = func(r *http.Request) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only pass those headers to the upgrader.
|
// Only pass those headers to the upgrader.
|
||||||
upgradeHeader := http.Header{}
|
upgradeHeader := http.Header{}
|
||||||
if hdr := resp.Header.Get("Sec-Websocket-Protocol"); hdr != "" {
|
if hdr := resp.Header.Get("Sec-Websocket-Protocol"); hdr != "" {
|
||||||
|
@ -28,7 +28,10 @@ func TestProxy(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u, _ := url.Parse(backendURL)
|
u, _ := url.Parse(backendURL)
|
||||||
proxy := NewProxy(u, false)
|
proxy := NewProxy(u, Options{
|
||||||
|
SkipTLSValidation: false,
|
||||||
|
SkipOriginCheck: false,
|
||||||
|
})
|
||||||
proxy.Upgrader = upgrader
|
proxy.Upgrader = upgrader
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
|
14
src/start.go
14
src/start.go
@ -12,6 +12,7 @@ import (
|
|||||||
"imuslab.com/zoraxy/mod/auth"
|
"imuslab.com/zoraxy/mod/auth"
|
||||||
"imuslab.com/zoraxy/mod/database"
|
"imuslab.com/zoraxy/mod/database"
|
||||||
"imuslab.com/zoraxy/mod/dynamicproxy/redirection"
|
"imuslab.com/zoraxy/mod/dynamicproxy/redirection"
|
||||||
|
"imuslab.com/zoraxy/mod/forwardproxy"
|
||||||
"imuslab.com/zoraxy/mod/ganserv"
|
"imuslab.com/zoraxy/mod/ganserv"
|
||||||
"imuslab.com/zoraxy/mod/geodb"
|
"imuslab.com/zoraxy/mod/geodb"
|
||||||
"imuslab.com/zoraxy/mod/info/logger"
|
"imuslab.com/zoraxy/mod/info/logger"
|
||||||
@ -219,6 +220,18 @@ func startupSequence() {
|
|||||||
//Create an analytic loader
|
//Create an analytic loader
|
||||||
AnalyticLoader = analytic.NewDataLoader(sysdb, statisticCollector)
|
AnalyticLoader = analytic.NewDataLoader(sysdb, statisticCollector)
|
||||||
|
|
||||||
|
//Create basic forward proxy
|
||||||
|
sysdb.NewTable("fwdproxy")
|
||||||
|
fwdProxyEnabled := false
|
||||||
|
fwdProxyPort := 5587
|
||||||
|
sysdb.Read("fwdproxy", "port", &fwdProxyPort)
|
||||||
|
sysdb.Read("fwdproxy", "enabled", &fwdProxyEnabled)
|
||||||
|
forwardProxy = forwardproxy.NewForwardProxy(sysdb, fwdProxyPort, SystemWideLogger)
|
||||||
|
if fwdProxyEnabled {
|
||||||
|
SystemWideLogger.PrintAndLog("Forward Proxy", "HTTP Forward Proxy Listening on :"+strconv.Itoa(forwardProxy.Port), nil)
|
||||||
|
forwardProxy.Start()
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ACME API
|
ACME API
|
||||||
|
|
||||||
@ -241,4 +254,5 @@ func finalSequence() {
|
|||||||
|
|
||||||
//Inject routing rules
|
//Inject routing rules
|
||||||
registerBuildInRoutingRules()
|
registerBuildInRoutingRules()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,23 @@
|
|||||||
Paste to Terminal <code style="float: right;">Shift + Insert</code>
|
Paste to Terminal <code style="float: right;">Shift + Insert</code>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="ui divider"></div>
|
||||||
|
<h2>Forward Proxy</h2>
|
||||||
|
<p>Setup a basic HTTP forward proxy to access web server in another LAN<br>
|
||||||
|
To enable forward proxy in your domain, add a proxy rule to 127.0.0.1:{selected_port}</p>
|
||||||
|
<form class="ui form">
|
||||||
|
<div class="field">
|
||||||
|
<label>Listening Port</label>
|
||||||
|
<div class="ui action input">
|
||||||
|
<input id="forwardProxyPort" type="number" placeholder="5587" step="1", min="1024" max="65535" value="5587">
|
||||||
|
<button onclick="updateForwardProxyPort(); event.preventDefault();" class="ui basic button"><i class="ui green check icon"></i> Apply</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="forwardProxyButtons" class="field">
|
||||||
|
<button onclick="toggleForwadProxy(true); event.preventDefault();" class="ui basic small green button startBtn"><i class="ui green arrow alternate circle up icon"></i> Start</button>
|
||||||
|
<button onclick="toggleForwadProxy(false); event.preventDefault();" class="ui basic small red button stopBtn"><i class="ui red minus circle icon"></i> Stop</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
<h2>Wake On LAN</h2>
|
<h2>Wake On LAN</h2>
|
||||||
<p>Wake up a remote server by WOL Magic Packet or an IoT device</p>
|
<p>Wake up a remote server by WOL Magic Packet or an IoT device</p>
|
||||||
@ -558,6 +574,68 @@ function renderWhoisDomainTable(jsonData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Forward Proxy
|
||||||
|
function initForwardProxyInfo(){
|
||||||
|
$.get("/api/tools/fwdproxy/enable", function(data){
|
||||||
|
if (data == true){
|
||||||
|
//Disable the start btn
|
||||||
|
$("#forwardProxyButtons").find(".startBtn").addClass('disabled');
|
||||||
|
$("#forwardProxyButtons").find(".stopBtn").removeClass('disabled');
|
||||||
|
}else{
|
||||||
|
$("#forwardProxyButtons").find(".startBtn").removeClass('disabled');
|
||||||
|
$("#forwardProxyButtons").find(".stopBtn").addClass('disabled');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.get("/api/tools/fwdproxy/port", function(data){
|
||||||
|
$("#forwardProxyPort").val(data);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
initForwardProxyInfo();
|
||||||
|
|
||||||
|
function toggleForwadProxy(enabled){
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/tools/fwdproxy/enable",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
"enable": enabled
|
||||||
|
},
|
||||||
|
success: function(data){
|
||||||
|
if (data.error != undefined){
|
||||||
|
msgbox(data.error, false);
|
||||||
|
}else{
|
||||||
|
msgbox(`Forward proxy ${enabled?"enabled":"disabled"}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
initForwardProxyInfo();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateForwardProxyPort(){
|
||||||
|
let newPortNumber = $("#forwardProxyPort").val();
|
||||||
|
if (newPortNumber < 1024 || newPortNumber > 65535){
|
||||||
|
$("#newPortNumber").parent().addClass('error');
|
||||||
|
}else{
|
||||||
|
$("#newPortNumber").parent().removeClass('error');
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "/api/tools/fwdproxy/port",
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
"port": newPortNumber
|
||||||
|
},
|
||||||
|
success: function(data){
|
||||||
|
if (data.error != undefined){
|
||||||
|
msgbox(data.error, false);
|
||||||
|
}
|
||||||
|
msgbox("Forward proxy port updated");
|
||||||
|
initForwardProxyInfo();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
<p>You might find these tools or information helpful when setting up your gateway server</p>
|
<p>You might find these tools or information helpful when setting up your gateway server</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui top attached tabular menu">
|
<div class="ui top attached tabular menu">
|
||||||
<a class="nettools item active" data-tab="tab1"><i class="ui user circle blue icon"></i> Accounts</a>
|
<a class="utils item active" data-tab="utiltab1"><i class="ui user circle blue icon"></i> Accounts</a>
|
||||||
<a class="nettools item" data-tab="tab2">Toolbox</a>
|
<a class="utils item" data-tab="utiltab2">Toolbox</a>
|
||||||
<a class="nettools item" data-tab="tab3">System</a>
|
<a class="utils item" data-tab="utiltab3">System</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ui bottom attached tab segment nettoolstab active" data-tab="tab1">
|
<div class="ui bottom attached tab segment utilitiesTabs active" data-tab="utiltab1">
|
||||||
<div class="extAuthOnly" style="display:none;">
|
<div class="extAuthOnly" style="display:none;">
|
||||||
<div class="ui basic segment">
|
<div class="ui basic segment">
|
||||||
<i class="ui green circle check icon"></i> Account options are not available due to -noauth flag is set to true.
|
<i class="ui green circle check icon"></i> Account options are not available due to -noauth flag is set to true.
|
||||||
@ -99,7 +99,7 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui bottom attached tab segment nettoolstab" data-tab="tab2">
|
<div class="ui bottom attached tab segment utilitiesTabs" data-tab="utiltab2">
|
||||||
<h3> IP Address to CIDR</h3>
|
<h3> IP Address to CIDR</h3>
|
||||||
<p>No experience with CIDR notations? Here are some tools you can use to make setting up easier.</p>
|
<p>No experience with CIDR notations? Here are some tools you can use to make setting up easier.</p>
|
||||||
<div class="ui basic segment">
|
<div class="ui basic segment">
|
||||||
@ -128,7 +128,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ui bottom attached tab segment nettoolstab" data-tab="tab3">
|
<div class="ui bottom attached tab segment utilitiesTabs" data-tab="utiltab3">
|
||||||
<!-- Config Tools -->
|
<!-- Config Tools -->
|
||||||
<h3>System Backup & Restore</h3>
|
<h3>System Backup & Restore</h3>
|
||||||
<p>Options related to system backup, migrate and restore.</p>
|
<p>Options related to system backup, migrate and restore.</p>
|
||||||
@ -175,7 +175,16 @@
|
|||||||
<br>
|
<br>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
$('.menu .nettools.item').tab();
|
$('.menu .utils.item').tab();
|
||||||
|
// Switch tabs when clicking on the menu items
|
||||||
|
$('.menu .utils.item').on('click', function() {
|
||||||
|
$('.menu .utils.item').removeClass('active');
|
||||||
|
$(this).addClass('active');
|
||||||
|
var tab = $(this).attr('data-tab');
|
||||||
|
$('.utilitiesTabs.tab.segment').removeClass('active');
|
||||||
|
$('div[data-tab="' + tab + '"]').addClass('active');
|
||||||
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Account Password utilities
|
Account Password utilities
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user