Files
zoraxy/src/mod/access/accessRule.go
Toby Chui 8e648a8e1f v3.0.2 init commit
+ Fixed zeroSSL bug (said by @yeungalan ) #45
+ Fixed manual renew button bug
+ Seperated geodb module with access controller
+ Added per hosts access control (experimental) #69
+ Fixed basic auth not working on TLS bypass mode bug
+ Fixed empty domain crash bug #120
2024-04-14 19:37:01 +08:00

154 lines
3.4 KiB
Go

package access
import (
"encoding/json"
"errors"
"net"
"os"
"path/filepath"
)
// Check both blacklist and whitelist for access for both geoIP and ip / CIDR ranges
func (s *AccessRule) AllowIpAccess(ipaddr string) bool {
if s.IsBlacklisted(ipaddr) {
return false
}
return s.IsWhitelisted(ipaddr)
}
// Check both blacklist and whitelist for access using net.Conn
func (s *AccessRule) AllowConnectionAccess(conn net.Conn) bool {
if addr, ok := conn.RemoteAddr().(*net.TCPAddr); ok {
return s.AllowIpAccess(addr.IP.String())
}
return true
}
// Toggle black list
func (s *AccessRule) ToggleBlacklist(enabled bool) {
s.BlacklistEnabled = enabled
s.SaveChanges()
}
// Toggel white list
func (s *AccessRule) ToggleWhitelist(enabled bool) {
s.WhitelistEnabled = enabled
s.SaveChanges()
}
/*
Check if a IP address is blacklisted, in either country or IP blacklist
IsBlacklisted default return is false (allow access)
*/
func (s *AccessRule) IsBlacklisted(ipAddr string) bool {
if !s.BlacklistEnabled {
//Blacklist not enabled. Always return false
return false
}
if ipAddr == "" {
//Unable to get the target IP address
return false
}
countryCode, err := s.parent.Options.GeoDB.ResolveCountryCodeFromIP(ipAddr)
if err != nil {
return false
}
if s.IsCountryCodeBlacklisted(countryCode.CountryIsoCode) {
return true
}
if s.IsIPBlacklisted(ipAddr) {
return true
}
return false
}
/*
IsWhitelisted check if a given IP address is in the current
server's white list.
Note that the Whitelist default result is true even
when encountered error
*/
func (s *AccessRule) IsWhitelisted(ipAddr string) bool {
if !s.WhitelistEnabled {
//Whitelist not enabled. Always return true (allow access)
return true
}
if ipAddr == "" {
//Unable to get the target IP address, assume ok
return true
}
countryCode, err := s.parent.Options.GeoDB.ResolveCountryCodeFromIP(ipAddr)
if err != nil {
return true
}
if s.IsCountryCodeWhitelisted(countryCode.CountryIsoCode) {
return true
}
if s.IsIPWhitelisted(ipAddr) {
return true
}
return false
}
/* Utilities function */
// Update the current access rule to json file
func (s *AccessRule) SaveChanges() error {
if s.parent == nil {
return errors.New("save failed: access rule detached from controller")
}
saveTarget := filepath.Join(s.parent.Options.ConfigFolder, s.ID+".json")
js, err := json.MarshalIndent(s, "", " ")
if err != nil {
return err
}
err = os.WriteFile(saveTarget, js, 0775)
return err
}
// Delete this access rule, this will only delete the config file.
// for runtime delete, use DeleteAccessRuleByID from parent Controller
func (s *AccessRule) DeleteConfigFile() error {
saveTarget := filepath.Join(s.parent.Options.ConfigFolder, s.ID+".json")
return os.Remove(saveTarget)
}
// Delete the access rule by given ID
func (c *Controller) DeleteAccessRuleByID(accessRuleID string) error {
targetAccessRule, err := c.GetAccessRuleByID(accessRuleID)
if err != nil {
return err
}
//Delete config file associated with this access rule
err = targetAccessRule.DeleteConfigFile()
if err != nil {
return err
}
//Delete the access rule in runtime
c.ProxyAccessRule.Delete(accessRuleID)
return nil
}
// Create a deep copy object of the access rule list
func deepCopy(valueList map[string]string) map[string]string {
result := map[string]string{}
js, _ := json.Marshal(valueList)
json.Unmarshal(js, &result)
return result
}