mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-08-10 23:27:50 +02:00
Fixed #573
- Added whitelist loopback quick toggle - Fixed plugin exit stuck bug
This commit is contained in:
@@ -94,7 +94,7 @@ func NewAccessController(options *Options) (*Controller, error) {
|
||||
thisAccessRule := AccessRule{}
|
||||
err = json.Unmarshal(configContent, &thisAccessRule)
|
||||
if err != nil {
|
||||
options.Logger.PrintAndLog("Access", "Unable to parse config "+filepath.Base(configFile), err)
|
||||
options.Logger.PrintAndLog("access", "Unable to parse config "+filepath.Base(configFile), err)
|
||||
continue
|
||||
}
|
||||
thisAccessRule.parent = &thisController
|
||||
@@ -102,6 +102,19 @@ func NewAccessController(options *Options) (*Controller, error) {
|
||||
}
|
||||
thisController.ProxyAccessRule = &ProxyAccessRules
|
||||
|
||||
//Start the public ip ticker
|
||||
if options.PublicIpCheckInterval <= 0 {
|
||||
options.PublicIpCheckInterval = 12 * 60 * 60 //12 hours
|
||||
}
|
||||
thisController.ServerPublicIP = "127.0.0.1"
|
||||
go func() {
|
||||
err = thisController.UpdatePublicIP()
|
||||
if err != nil {
|
||||
options.Logger.PrintAndLog("access", "Unable to update public IP address", err)
|
||||
}
|
||||
|
||||
thisController.StartPublicIPUpdater()
|
||||
}()
|
||||
return &thisController, nil
|
||||
}
|
||||
|
||||
@@ -147,11 +160,7 @@ func (c *Controller) ListAllAccessRules() []*AccessRule {
|
||||
// Check if an access rule exists given the rule id
|
||||
func (c *Controller) AccessRuleExists(ruleID string) bool {
|
||||
r, _ := c.GetAccessRuleByID(ruleID)
|
||||
if r != nil {
|
||||
//An access rule with identical ID exists
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return r != nil
|
||||
}
|
||||
|
||||
// Add a new access rule to runtime and save it to file
|
||||
@@ -219,3 +228,7 @@ func (c *Controller) RemoveAccessRuleByID(ruleID string) error {
|
||||
//Remove it
|
||||
return c.DeleteAccessRuleByID(ruleID)
|
||||
}
|
||||
|
||||
func (c *Controller) Close() {
|
||||
c.StopPublicIPUpdater()
|
||||
}
|
||||
|
@@ -25,18 +25,24 @@ func (s *AccessRule) AllowConnectionAccess(conn net.Conn) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Toggle black list
|
||||
// Toggle blacklist
|
||||
func (s *AccessRule) ToggleBlacklist(enabled bool) {
|
||||
s.BlacklistEnabled = enabled
|
||||
s.SaveChanges()
|
||||
}
|
||||
|
||||
// Toggel white list
|
||||
// Toggel whitelist
|
||||
func (s *AccessRule) ToggleWhitelist(enabled bool) {
|
||||
s.WhitelistEnabled = enabled
|
||||
s.SaveChanges()
|
||||
}
|
||||
|
||||
// Toggle whitelist loopback
|
||||
func (s *AccessRule) ToggleAllowLoopback(enabled bool) {
|
||||
s.WhitelistAllowLocalAndLoopback = enabled
|
||||
s.SaveChanges()
|
||||
}
|
||||
|
||||
/*
|
||||
Check if a IP address is blacklisted, in either country or IP blacklist
|
||||
IsBlacklisted default return is false (allow access)
|
||||
|
134
src/mod/access/loopback.go
Normal file
134
src/mod/access/loopback.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package access
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
PUBLIC_IP_CHECK_URL = "http://checkip.amazonaws.com/"
|
||||
)
|
||||
|
||||
// Start the public IP address updater
|
||||
func (c *Controller) StartPublicIPUpdater() {
|
||||
stopChan := make(chan bool)
|
||||
c.publicIpTickerStop = stopChan
|
||||
ticker := time.NewTicker(time.Duration(c.Options.PublicIpCheckInterval) * time.Second)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-stopChan:
|
||||
ticker.Stop()
|
||||
return
|
||||
case <-ticker.C:
|
||||
err := c.UpdatePublicIP()
|
||||
if err != nil {
|
||||
c.Options.Logger.PrintAndLog("access", "Unable to update public IP address", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
c.publicIpTicker = ticker
|
||||
}
|
||||
|
||||
// Stop the public IP address updater
|
||||
func (c *Controller) StopPublicIPUpdater() {
|
||||
// Stop the public IP address updater
|
||||
if c.publicIpTickerStop != nil {
|
||||
c.publicIpTickerStop <- true
|
||||
}
|
||||
c.publicIpTicker = nil
|
||||
c.publicIpTickerStop = nil
|
||||
}
|
||||
|
||||
// Update the public IP address of the server
|
||||
func (c *Controller) UpdatePublicIP() error {
|
||||
req, err := http.NewRequest("GET", PUBLIC_IP_CHECK_URL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3")
|
||||
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
|
||||
req.Header.Set("Accept-Language", "en-US,en;q=0.5")
|
||||
req.Header.Set("Connection", "keep-alive")
|
||||
req.Header.Set("Upgrade-Insecure-Requests", "1")
|
||||
req.Header.Set("sec-ch-ua", `"Chromium";v="91", " Not;A Brand";v="99", "Google Chrome";v="91"`)
|
||||
req.Header.Set("sec-ch-ua-platform", `"Windows"`)
|
||||
req.Header.Set("sec-ch-ua-mobile", "?0")
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
ip, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Validate if the returned byte is a valid IP address
|
||||
pubIP := net.ParseIP(strings.TrimSpace(string(ip)))
|
||||
if pubIP == nil {
|
||||
return errors.New("invalid IP address")
|
||||
}
|
||||
|
||||
c.ServerPublicIP = pubIP.String()
|
||||
c.Options.Logger.PrintAndLog("access", "Public IP address updated to: "+c.ServerPublicIP, nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) IsLoopbackRequest(ipAddr string) bool {
|
||||
loopbackIPs := []string{
|
||||
"localhost",
|
||||
"::1",
|
||||
"127.0.0.1",
|
||||
}
|
||||
|
||||
// Check if the request is loopback from public IP
|
||||
if ipAddr == c.ServerPublicIP {
|
||||
return true
|
||||
}
|
||||
|
||||
// Check if the request is from localhost or loopback IPv4 or 6
|
||||
for _, loopbackIP := range loopbackIPs {
|
||||
if ipAddr == loopbackIP {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if the IP address is in private IP range
|
||||
func (c *Controller) IsPrivateIPRange(ipAddr string) bool {
|
||||
privateIPBlocks := []string{
|
||||
"10.0.0.0/8",
|
||||
"172.16.0.0/12",
|
||||
"192.168.0.0/16",
|
||||
"169.254.0.0/16",
|
||||
"127.0.0.0/8",
|
||||
"::1/128",
|
||||
"fc00::/7",
|
||||
"fe80::/10",
|
||||
}
|
||||
|
||||
for _, cidr := range privateIPBlocks {
|
||||
_, block, err := net.ParseCIDR(cidr)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ip := net.ParseIP(ipAddr)
|
||||
if block.Contains(ip) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
@@ -2,6 +2,7 @@ package access
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"imuslab.com/zoraxy/mod/database"
|
||||
"imuslab.com/zoraxy/mod/geodb"
|
||||
@@ -13,14 +14,18 @@ type Options struct {
|
||||
ConfigFolder string //Path for storing config files
|
||||
GeoDB *geodb.Store //For resolving country code
|
||||
Database *database.Database //System key-value database
|
||||
|
||||
/* Public IP monitoring */
|
||||
PublicIpCheckInterval int64 //in Seconds
|
||||
}
|
||||
|
||||
type AccessRule struct {
|
||||
ID string
|
||||
Name string
|
||||
Desc string
|
||||
BlacklistEnabled bool
|
||||
WhitelistEnabled bool
|
||||
ID string
|
||||
Name string
|
||||
Desc string
|
||||
BlacklistEnabled bool
|
||||
WhitelistEnabled bool
|
||||
WhitelistAllowLocalAndLoopback bool //Allow local and loopback address to bypass whitelist
|
||||
|
||||
/* Whitelist Blacklist Table, value is comment if supported */
|
||||
WhiteListCountryCode *map[string]string
|
||||
@@ -32,7 +37,12 @@ type AccessRule struct {
|
||||
}
|
||||
|
||||
type Controller struct {
|
||||
ServerPublicIP string
|
||||
DefaultAccessRule *AccessRule
|
||||
ProxyAccessRule *sync.Map
|
||||
Options *Options
|
||||
|
||||
//Internal
|
||||
publicIpTicker *time.Ticker
|
||||
publicIpTickerStop chan bool
|
||||
}
|
||||
|
@@ -93,6 +93,13 @@ func (s *AccessRule) IsIPWhitelisted(ipAddr string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
//Check for loopback match
|
||||
if s.WhitelistAllowLocalAndLoopback {
|
||||
if s.parent.IsLoopbackRequest(ipAddr) || s.parent.IsPrivateIPRange(ipAddr) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user