This commit is contained in:
root 2024-02-16 23:37:45 +02:00
commit 5c957adccf
46 changed files with 12287 additions and 0 deletions

95
ad/ad.go Executable file
View File

@ -0,0 +1,95 @@
package ad
import (
"fmt"
"github.com/go-ldap/ldap/v3"
"github.com/techoner/gophp"
"handlers"
"log"
"strconv"
"strings"
)
var (
SelfADLdapServer string
SelfADLdapPort int
SelfADLdapIsSSL bool
SelfADLdapSSL string
SelfADLdapFQDN string
SelfADLdapUsername string
SelfADLdapSuffix string
SelfADLdapPassword string
SelfADConnections []interface{}
DebugAD bool
)
func init() {
activeDirectoryConnectionsData := handlers.GetSocketInfoString("ActiveDirectoryConnections")
if len(activeDirectoryConnectionsData) == 0 {
if DebugAD {
log.Printf("ActiveDirectoryConnections Len=0")
}
}
out, err := gophp.Unserialize([]byte(activeDirectoryConnectionsData))
if err != nil {
if DebugAD {
log.Printf("error Unserialize itcharts.ids: ", err)
}
}
SelfADConnections = out.([]interface{})
}
func LoadConnection(connID int) bool {
for d, data := range SelfADConnections {
if d == connID {
for k, v := range data.(map[string]interface{}) {
if k == "LDAP_SUFFIX" {
SelfADLdapSuffix = v.(string)
}
if k == "LDAP_PASSWORD" {
SelfADLdapPassword = v.(string)
}
if k == "LDAP_SERVER" {
SelfADLdapServer = v.(string)
}
if k == "LDAP_PORT" {
SelfADLdapPort, _ = strconv.Atoi(v.(string))
}
if k == "LDAP_DN" {
SelfADLdapUsername = v.(string)
}
if k == "LDAP_SSL" {
SelfADLdapSSL = v.(string)
}
}
}
ldapSuffix = strings.ToLower(activeDirectoryConnections["LDAP_SUFFIX"].(string))
ldapPassword = activeDirectoryConnections["LDAP_PASSWORD"].(string)
ldapServer = activeDirectoryConnections["LDAP_SERVER"].(string)
ldapPort = activeDirectoryConnections["LDAP_PORT"].(int)
ldapUsername = activeDirectoryConnections["LDAP_DN"].(string)
if _, ok := activeDirectoryConnections["LDAP_SSL"]; ok {
ldapSSL = activeDirectoryConnections["LDAP_SSL"].(string)
}
if ldapPort == 636 {
ldapIsSSL = true
}
}
func Connect() (*ldap.Conn, error) {
proto := "ldap"
if ldapIsSSL {
proto = "ldaps"
}
// You can also use IP instead of FQDN
l, err := ldap.DialURL(fmt.Sprintf("%s://%s:%d", proto, ldapServer, ldapPort))
if err != nil {
if isDebug {
log.Printf("Failed to connect to ldap %s://%s:%d with error %s", proto, ldapServer, ldapPort, err)
}
return nil, err
}
return l, nil
}

19
ad/go.mod Executable file
View File

@ -0,0 +1,19 @@
module ad
go 1.18
replace handlers => ../handlers
require (
github.com/go-ldap/ldap/v3 v3.4.3
github.com/techoner/gophp v0.2.0
handlers v0.0.0-00010101000000-000000000000
)
require (
github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e // indirect
github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect
github.com/leekchan/timeutil v0.0.0-20150802142658-28917288c48d // indirect
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 // indirect
)

21
ad/go.sum Executable file
View File

@ -0,0 +1,21 @@
github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e h1:ZU22z/2YRFLyf/P4ZwUYSdNCWsMEI0VeyrFoI2rAhJQ=
github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-ldap/ldap/v3 v3.4.3 h1:JCKUtJPIcyOuG7ctGabLKMgIlKnGumD/iGjuWeEruDI=
github.com/go-ldap/ldap/v3 v3.4.3/go.mod h1:7LdHfVt6iIOESVEe3Bs4Jp2sHEKgDeduAhgM1/f9qmo=
github.com/leekchan/timeutil v0.0.0-20150802142658-28917288c48d h1:2puqoOQwi3Ai1oznMOsFIbifm6kIfJaLLyYzWD4IzTs=
github.com/leekchan/timeutil v0.0.0-20150802142658-28917288c48d/go.mod h1:hO90vCP2x3exaSH58BIAowSKvV+0OsY21TtzuFGHON4=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/techoner/gophp v0.2.0 h1:vVFoS2XC/NZariagUOhAGqC8p/Ws8R8ARYpj/9lTIAo=
github.com/techoner/gophp v0.2.0/go.mod h1:NOxB/qoTl4+G82CkQp60T18Az5rOTufCqm83x9i/u7M=
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o=
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

8
client/external_acl_first/.idea/.gitignore vendored Executable file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData" autoUpload="Always" serverName="Proxy1" remoteFilesAllowedToDisappearOnAutoupload="false">
<serverData>
<paths name="Proxy1">
<serverdata>
<mappings>
<mapping deploy="/" local="$PROJECT_DIR$" web="/" />
</mappings>
</serverdata>
</paths>
</serverData>
<option name="myAutoUpload" value="ALWAYS" />
</component>
</project>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/external_acl_first.iml" filepath="$PROJECT_DIR$/.idea/external_acl_first.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SshConfigs">
<configs>
<sshConfig authType="PASSWORD" connectionConfig="{&quot;serverAliveInterval&quot;:300}" host="192.168.60.156" id="7e114f00-77e5-4d33-b4f5-9fe750cba132" port="22" nameFormat="DESCRIPTIVE" username="root" useOpenSSHConfig="true" />
</configs>
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WebServers">
<option name="servers">
<webServer id="055f8a5b-1b5b-4da5-b773-0178a68a9aad" name="Proxy1">
<fileTransfer rootFolder="/usr/share/artica-postfix/bin/go-shield/client/external_acl_first" accessType="SFTP" host="192.168.60.156" port="22" sshConfigId="7e114f00-77e5-4d33-b4f5-9fe750cba132" sshConfig="root@192.168.60.156:22 password">
<advancedOptions>
<advancedOptions dataProtectionLevel="Private" passiveMode="true" shareSSLContext="true" />
</advancedOptions>
</fileTransfer>
</webServer>
</option>
</component>
</project>

Binary file not shown.

View File

@ -0,0 +1,27 @@
module external_acl_first
go 1.18
replace handlers => ../../handlers
replace storage => ../../storage
require (
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d
github.com/techoner/gophp v0.2.0
github.com/valyala/fasthttp v1.34.0
handlers v0.0.0-00010101000000-000000000000
storage v0.0.0-00010101000000-000000000000
)
require (
github.com/allegro/bigcache/v3 v3.0.2 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/klauspost/compress v1.15.0 // indirect
github.com/leekchan/timeutil v0.0.0-20150802142658-28917288c48d // indirect
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
)

View File

@ -0,0 +1,47 @@
github.com/allegro/bigcache/v3 v3.0.2 h1:AKZCw+5eAaVyNTBmI2fgyPVJhHkdWder3O9IrprcQfI=
github.com/allegro/bigcache/v3 v3.0.2/go.mod h1:aPyh7jEvrog9zAwx5N7+JUQX5dZTSGpxF1LAR4dr35I=
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d h1:pVrfxiGfwelyab6n21ZBkbkmbevaf+WvMIiR7sr97hw=
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U=
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/leekchan/timeutil v0.0.0-20150802142658-28917288c48d h1:2puqoOQwi3Ai1oznMOsFIbifm6kIfJaLLyYzWD4IzTs=
github.com/leekchan/timeutil v0.0.0-20150802142658-28917288c48d/go.mod h1:hO90vCP2x3exaSH58BIAowSKvV+0OsY21TtzuFGHON4=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/techoner/gophp v0.2.0 h1:vVFoS2XC/NZariagUOhAGqC8p/Ws8R8ARYpj/9lTIAo=
github.com/techoner/gophp v0.2.0/go.mod h1:NOxB/qoTl4+G82CkQp60T18Az5rOTufCqm83x9i/u7M=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.34.0 h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4=
github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,29 @@
package internal
import (
"github.com/bradfitz/gomemcache/memcache"
"log"
)
var MC = memcache.New("/var/run/memcached.sock")
func Get(key string, isDebug bool) string {
val, err := MC.Get(key)
if err != nil {
if isDebug {
log.Printf("Memcached Get->Error: %s", err)
}
panic(err)
}
if string(val.Value) == "" {
return ""
}
return string(val.Value)
}
func Set(key string, value []byte, ttl int32) {
err := MC.Set(&memcache.Item{Key: key, Value: value, Expiration: ttl})
if err != nil {
panic(err)
}
}

181
client/external_acl_first/main.go Executable file
View File

@ -0,0 +1,181 @@
package main
import (
"bufio"
b64 "encoding/base64"
"github.com/bradfitz/gomemcache/memcache"
"log/syslog"
"net"
"os/signal"
"runtime/debug"
"strings"
"syscall"
"time"
//_ "expvar"
"fmt"
"github.com/valyala/fasthttp"
"handlers"
"log"
"os"
"storage"
"strconv"
"sync"
)
var (
rewriter_exit_chan chan int = make(chan int, 1)
response_chan chan string = make(chan string, 1024*10)
signal_hup_chan chan os.Signal = make(chan os.Signal, 1)
stdin_line_chan chan string = make(chan string, 200)
signalInterruptChan chan os.Signal = make(chan os.Signal, 1)
)
var (
addr = "127.0.0.1"
port int = 3333
//CONN_TYPE = "tcp"
version = "1.0.11"
isDebug bool = false
timeOut int = 5
SelfSquidUrgency bool
strContentType = []byte("Content-Type")
strApplicationJSON = []byte("application/json")
)
type CategoriesResponse struct {
Category_id string
Category_name string
}
//var answer *string
//var err error
func init() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
if _slog, err := syslog.New(syslog.LOG_DEBUG, "go-shield-connector"); err == nil {
log.SetOutput(_slog)
}
signal.Notify(signal_hup_chan, syscall.SIGHUP)
signal.Notify(signalInterruptChan, os.Interrupt, syscall.SIGTERM)
}
func main() {
defer func() {
if r := recover(); r != nil {
log.Printf("Panic: %v,\n%s", r, debug.Stack())
os.Exit(1)
}
}()
addr = handlers.GetSocketInfoString("Go_Shield_Connector_Addr")
port = handlers.GetSocketInfoInt("Go_Shield_Connector_Port")
isDebug = handlers.GetSocketInfoBool("Go_Shield_Connector_Debug")
timeOut = handlers.GetSocketInfoInt("Go_Shield_Connector_TimeOut")
SelfSquidUrgency = handlers.GetSocketInfoBool("SquidUrgency")
if addr == "" {
addr = "127.0.0.1"
}
if port == 0 {
port = 3333
}
if timeOut == 0 {
timeOut = 5
}
//dns1_token_int, _ := strconv.Atoi(dns1_token)
//dns2_token_int, _ := strconv.Atoi(dns2_token)
//addr_token_int, _ := strconv.Atoi(addr_token)
//port_token_int, _ := strconv.Atoi(port_token)
//internal.SetSocketInfo("Go_Shield_Connector_Version", version)
//addr_token_int, _ := strconv.Atoi(addr_token)
//port_token_int, _ := strconv.Atoi(port_token)
//mc := memcache.New("/var/run/memcached.sock")
storage.MC.Set(&memcache.Item{Key: "Go-Shield-Connector-Version", Value: []byte(version), Expiration: 2590000})
isDebug = true
var wg sync.WaitGroup
reader := bufio.NewReader(os.Stdin)
//http.ListenAndServe(":1234", nil)
for {
line, err := reader.ReadString('\n')
if err != nil {
// You may check here if err == io.EOF
break
}
wg.Add(1)
go ProcessRequest(line, &wg)
}
wg.Wait()
}
func ProcessRequest(line string, wg *sync.WaitGroup) {
defer func() {
if r := recover(); r != nil {
log.Printf("Panic: %v,\n%s", r, debug.Stack())
os.Exit(1)
}
}()
defer wg.Done()
start := time.Now()
lparts := strings.Split(strings.TrimRight(line, "\n"), " ")
id := lparts[0]
query := b64.URLEncoding.EncodeToString([]byte(line))
if SelfSquidUrgency {
if isDebug {
log.Printf("WARNING... Emergency Enabled")
}
defer wg.Done()
fmt.Println(id + "OK first=EMERGENCY webfilter=pass\n")
return
}
if isDebug {
log.Printf("Receive <%s> Query <%s>", line, query)
}
req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req)
log.Printf("http://" + addr + ":" + strconv.Itoa(port) + "/external-acl-first/" + query)
req.SetRequestURI("http://" + addr + ":" + strconv.Itoa(port) + "/external-acl-first/" + query)
resp := fasthttp.AcquireResponse()
defer fasthttp.ReleaseResponse(resp)
client := &fasthttp.Client{
ReadTimeout: time.Duration(timeOut) * time.Second,
MaxIdleConnDuration: time.Duration(10) * time.Second,
Dial: func(addr string) (net.Conn, error) {
return fasthttp.DialTimeout(addr, time.Duration(timeOut)*time.Second)
},
//TLSConfig: &tls.Config{InsecureSkipVerify: true},
}
//client.Do(req, resp)
if err := client.DoTimeout(req, resp, time.Duration(timeOut)*time.Second); err != nil {
fmt.Println(id + " OK first=ERROR")
return
}
bodyBytes := resp.Body()
code := resp.StatusCode()
if code == 200 {
//defer wg.Done()
elapsed := time.Since(start).Microseconds()
if isDebug {
log.Printf("FINISH PARSING - Resp = %s | code = %d - took %d μs", bodyBytes, code, elapsed)
}
fmt.Print(string(bodyBytes))
return
}
//defer wg.Done()
if isDebug {
log.Printf("Invalid - Resp = %s | code = %d", bodyBytes, code)
}
fmt.Print(id + "OK first=ERROR webfilter=pass exterr=invalid_code_%d\n")
return
}

Binary file not shown.

Binary file not shown.

BIN
exec/go-exec Executable file

Binary file not shown.

BIN
exec/go-forker Executable file

Binary file not shown.

Binary file not shown.

BIN
go-failover-checker Executable file

Binary file not shown.

9
handlers/go.mod Executable file
View File

@ -0,0 +1,9 @@
module handlers
go 1.18
require (
github.com/leekchan/timeutil v0.0.0-20150802142658-28917288c48d
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/techoner/gophp v0.2.0
)

6
handlers/go.sum Executable file
View File

@ -0,0 +1,6 @@
github.com/leekchan/timeutil v0.0.0-20150802142658-28917288c48d h1:2puqoOQwi3Ai1oznMOsFIbifm6kIfJaLLyYzWD4IzTs=
github.com/leekchan/timeutil v0.0.0-20150802142658-28917288c48d/go.mod h1:hO90vCP2x3exaSH58BIAowSKvV+0OsY21TtzuFGHON4=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/techoner/gophp v0.2.0 h1:vVFoS2XC/NZariagUOhAGqC8p/Ws8R8ARYpj/9lTIAo=
github.com/techoner/gophp v0.2.0/go.mod h1:NOxB/qoTl4+G82CkQp60T18Az5rOTufCqm83x9i/u7M=

8
handlers/handlers.go Executable file
View File

@ -0,0 +1,8 @@
package handlers
var isDebug bool
func init() {
isDebug = GetSocketInfoBool("Go_Shield_Server_Debug")
}

97
handlers/license.go Executable file

File diff suppressed because one or more lines are too long

68
handlers/loggin.go Executable file
View File

@ -0,0 +1,68 @@
package handlers
import (
"fmt"
"github.com/leekchan/timeutil"
"github.com/op/go-logging"
"math"
"os"
"strconv"
"time"
)
var logstats = logging.MustGetLogger("ksrn-stats")
func IsInt(s string) bool {
_, err := strconv.Atoi(s)
return err == nil
}
func TimeTrack(start time.Time) string {
//elapsed := time.Since(start)
//log.Printf("%s took %dms", name, elapsed.Nanoseconds()/1000)
return fmt.Sprintf("took %d μs", time.Since(start).Microseconds())
}
func GetTimeDelta(delta time.Duration, format int) string {
if delta == 0 {
delta = 1
}
d := time.Minute * delta
deltaSeconds := float64(d / time.Second) //delta time in seconds
t := time.Now()
s := daySeconds(t) // seconds
ms := t.Nanosecond() / 1000 //Microseconds
r := math.Floor((float64(s)+deltaSeconds/2)/deltaSeconds) * deltaSeconds //rounding
rs := int(r) //rounding in seconds
o := rs - s
td := timeutil.Timedelta{Days: 0, Seconds: time.Duration(o), Microseconds: time.Duration(-ms)}
result := t.Add(td.Duration())
var str string
if format == 1 {
str = timeutil.Strftime(&result, "%Y%m%d%H%M")
}
if format == 2 {
str = timeutil.Strftime(&result, "%Y-%m-%d %H:%M:%S")
}
return str
}
func daySeconds(t time.Time) int {
year, month, day := t.Date()
t2 := time.Date(year, month, day, 0, 0, 0, 0, t.Location())
return int(t.Sub(t2).Seconds())
}
func Logfile(filename, data string) {
f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
logstats.Fatal(err)
}
defer f.Close()
backend := logging.NewLogBackend(f, "", 0)
logging.SetBackend(backend)
logstats.Info(data)
//mylog.SetOutput(f)
//mylog.Println(data)
}

94
handlers/tokens.go Executable file
View File

@ -0,0 +1,94 @@
package handlers
import (
"bytes"
"errors"
"log"
"os"
"strconv"
)
func GetSocketInfoInt(token string) int {
if _, err := os.Stat("/etc/artica-postfix/settings/Daemons/" + token); errors.Is(err, os.ErrNotExist) {
if isDebug {
log.Printf("Token %s dont exist %s", token, err)
}
return 0
}
tk, err := os.ReadFile("/etc/artica-postfix/settings/Daemons/" + token)
if err != nil {
if isDebug {
log.Printf("Failed read file %s %s %s", token, tk, err)
}
return 0
}
tk = bytes.TrimSuffix(tk, []byte("\n"))
tk = bytes.TrimSpace(tk)
tkint, err := strconv.Atoi(string(tk))
if err == nil {
if isDebug {
log.Printf("Init converted file %s val %s => %d", token, tk, tkint)
}
return tkint
} else {
if isDebug {
log.Printf("Failed to convert to init token %s => %d", token, tkint)
}
return 0
}
return 0
}
func GetSocketInfoBool(token string) bool {
if _, err := os.Stat("/etc/artica-postfix/settings/Daemons/" + token); errors.Is(err, os.ErrNotExist) {
if isDebug {
log.Printf("Token %s dont exist %s", token, err)
}
return false
}
tk, err := os.ReadFile("/etc/artica-postfix/settings/Daemons/" + token)
if err != nil {
if isDebug {
log.Printf("Failed read file %s %s %s", token, tk, err)
}
return false
}
tk = bytes.TrimSuffix(tk, []byte("\n"))
tk = bytes.TrimSpace(tk)
boolValue, err := strconv.ParseBool(string(tk))
if err == nil {
if isDebug {
log.Printf("Bool converted file %s val %s => %t", token, tk, boolValue)
}
return boolValue
} else {
if isDebug {
log.Printf("Failed to convert to bool token %s => %s", token, err)
}
return false
}
return false
}
func GetSocketInfoString(token string) string {
if _, err := os.Stat("/etc/artica-postfix/settings/Daemons/" + token); errors.Is(err, os.ErrNotExist) {
if isDebug {
log.Printf("Token %s dont exist %s", token, err)
}
return ""
}
tk, err := os.ReadFile("/etc/artica-postfix/settings/Daemons/" + token)
if err != nil {
if isDebug {
log.Printf("Failed read file %s %s %s", token, tk, err)
}
return ""
}
if isDebug {
log.Printf("Token converted to string correctly %s val %s", token, tk)
}
return string(tk)
}

8
server/.idea/.gitignore vendored Executable file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

14
server/.idea/deployment.xml Executable file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PublishConfigData" serverName="Proxy1" remoteFilesAllowedToDisappearOnAutoupload="false">
<serverData>
<paths name="Proxy1">
<serverdata>
<mappings>
<mapping deploy="/" local="$PROJECT_DIR$" web="/" />
</mappings>
</serverdata>
</paths>
</serverData>
</component>
</project>

8
server/.idea/modules.xml Executable file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/server.iml" filepath="$PROJECT_DIR$/.idea/server.iml" />
</modules>
</component>
</project>

9
server/.idea/server.iml Executable file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
server/.idea/sshConfigs.xml Executable file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SshConfigs">
<configs>
<sshConfig authType="PASSWORD" host="192.168.60.156" id="7e114f00-77e5-4d33-b4f5-9fe750cba132" port="22" nameFormat="DESCRIPTIVE" username="root" useOpenSSHConfig="true" />
</configs>
</component>
</project>

7
server/.idea/vcs.xml Executable file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../.." vcs="Git" />
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

14
server/.idea/webServers.xml Executable file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WebServers">
<option name="servers">
<webServer id="91f7f8b1-294b-4011-b4dc-c520e96852ef" name="Proxy1">
<fileTransfer rootFolder="/usr/share/artica-postfix/bin/go-shield/server" accessType="SFTP" host="192.168.60.156" port="22" sshConfigId="7e114f00-77e5-4d33-b4f5-9fe750cba132" sshConfig="root@192.168.60.156:22 password">
<advancedOptions>
<advancedOptions dataProtectionLevel="Private" keepAliveTimeout="0" passiveMode="true" shareSSLContext="true" />
</advancedOptions>
</fileTransfer>
</webServer>
</option>
</component>
</project>

BIN
server/bin/go-shield-server Executable file

Binary file not shown.

File diff suppressed because it is too large Load Diff

52
server/go.mod Executable file
View File

@ -0,0 +1,52 @@
module server
go 1.18
replace handlers => ../handlers
replace storage => ../storage
replace categorization => ../categorization
replace shields => ../shields
replace ufdbguard => ../ufdbguard
replace itchart => ../itchart
require (
categorization v0.0.0-00010101000000-000000000000
github.com/facebookgo/pidfile v0.0.0-20150612191647-f242e2999868
github.com/fasthttp/router v1.4.6
github.com/oschwald/geoip2-golang v1.7.0
github.com/sirupsen/logrus v1.8.1
github.com/techoner/gophp v0.2.0
github.com/valyala/fasthttp v1.34.0
handlers v0.0.0-00010101000000-000000000000
shields v0.0.0-00010101000000-000000000000
storage v0.0.0-00010101000000-000000000000
ufdbguard v0.0.0-00010101000000-000000000000
)
require (
github.com/allegro/bigcache/v3 v3.0.2 // indirect
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/d3mondev/resolvermt v0.3.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/klauspost/compress v1.15.0 // indirect
github.com/leekchan/timeutil v0.0.0-20150802142658-28917288c48d // indirect
github.com/miekg/dns v1.1.40 // indirect
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect
github.com/oschwald/maxminddb-golang v1.9.0 // indirect
github.com/savsgio/gotils v0.0.0-20211223103454-d0aaa54c5899 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
go.uber.org/ratelimit v0.2.0 // indirect
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/sys v0.0.0-20220325203850-36772127a21f // indirect
)

112
server/go.sum Executable file
View File

@ -0,0 +1,112 @@
github.com/allegro/bigcache/v3 v3.0.2 h1:AKZCw+5eAaVyNTBmI2fgyPVJhHkdWder3O9IrprcQfI=
github.com/allegro/bigcache/v3 v3.0.2/go.mod h1:aPyh7jEvrog9zAwx5N7+JUQX5dZTSGpxF1LAR4dr35I=
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI=
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg=
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d h1:pVrfxiGfwelyab6n21ZBkbkmbevaf+WvMIiR7sr97hw=
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/d3mondev/resolvermt v0.3.2 h1:GuvpC6STaEiseETw86GX4HPkBcVqIBcOH1sqpO6qlz4=
github.com/d3mondev/resolvermt v0.3.2/go.mod h1:upm9SiedgEkrJ4YYxfnEPbtWvgxMwNd5oigx6dQLYhE=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A=
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg=
github.com/facebookgo/pidfile v0.0.0-20150612191647-f242e2999868 h1:KZ75X3ZCl6yy4jg9R1ziYoCZFDBRqildm+fGComWU7U=
github.com/facebookgo/pidfile v0.0.0-20150612191647-f242e2999868/go.mod h1:3Hzo46xzfVpIdv4lJw7YBp9fUJ7HpUgbjH1fFDgy4qM=
github.com/fasthttp/router v1.4.6 h1:KfETdHGBnvoBfBHeRe/8TVYz8Bp/mASBVC5UXO9CpZI=
github.com/fasthttp/router v1.4.6/go.mod h1:Iv800u3hYFNuBBcmJNs/VBVpub+JfBihGBp5spSocbw=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U=
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/leekchan/timeutil v0.0.0-20150802142658-28917288c48d h1:2puqoOQwi3Ai1oznMOsFIbifm6kIfJaLLyYzWD4IzTs=
github.com/leekchan/timeutil v0.0.0-20150802142658-28917288c48d/go.mod h1:hO90vCP2x3exaSH58BIAowSKvV+0OsY21TtzuFGHON4=
github.com/miekg/dns v1.1.40 h1:pyyPFfGMnciYUk/mXpKkVmeMQjfXqt3FAJ2hy7tPiLA=
github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/oschwald/geoip2-golang v1.7.0 h1:JW1r5AKi+vv2ujSxjKthySK3jo8w8oKWPyXsw+Qs/S8=
github.com/oschwald/geoip2-golang v1.7.0/go.mod h1:mdI/C7iK7NVMcIDDtf4bCKMJ7r0o7UwGeCo9eiitCMQ=
github.com/oschwald/maxminddb-golang v1.9.0 h1:tIk4nv6VT9OiPyrnDAfJS1s1xKDQMZOsGojab6EjC1Y=
github.com/oschwald/maxminddb-golang v1.9.0/go.mod h1:TK+s/Z2oZq0rSl4PSeAEoP0bgm82Cp5HyvYbt8K3zLY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/savsgio/gotils v0.0.0-20211223103454-d0aaa54c5899 h1:Orn7s+r1raRTBKLSc9DmbktTT04sL+vkzsbRD2Q8rOI=
github.com/savsgio/gotils v0.0.0-20211223103454-d0aaa54c5899/go.mod h1:oejLrk1Y/5zOF+c/aHtXqn3TFlzzbAgPWg8zBiAHDas=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/techoner/gophp v0.2.0 h1:vVFoS2XC/NZariagUOhAGqC8p/Ws8R8ARYpj/9lTIAo=
github.com/techoner/gophp v0.2.0/go.mod h1:NOxB/qoTl4+G82CkQp60T18Az5rOTufCqm83x9i/u7M=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.33.0/go.mod h1:KJRK/MXx0J+yd0c5hlR+s1tIHD72sniU8ZJjl97LIw4=
github.com/valyala/fasthttp v1.34.0 h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4=
github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/ratelimit v0.2.0 h1:UQE2Bgi7p2B85uP5dC2bbRtig0C+OeNRnNEafLjsLPA=
go.uber.org/ratelimit v0.2.0/go.mod h1:YYBV4e4naJvhpitQrWJu1vCpgB7CboMe0qhltKt6mUg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o=
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220325203850-36772127a21f h1:TrmogKRsSOxRMJbLYGrB4SBbW+LJcEllYBLME5Zk5pU=
golang.org/x/sys v0.0.0-20220325203850-36772127a21f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

318
server/internal/bigcache.go Executable file
View File

@ -0,0 +1,318 @@
package internal
import (
"bufio"
"crypto/md5"
"encoding/hex"
"errors"
"fmt"
"github.com/allegro/bigcache/v3"
"io"
"log"
"os"
"strconv"
"strings"
"time"
)
var InMemoryCache *bigcache.BigCache
var (
SelfLifeWindow time.Duration = 86400
SelfHardMaxCacheSize int = 2048
SelfShards = 512
isDebugBigCache bool
)
func InitBigcache(debug bool) {
SelfLifeWindow = time.Duration(GetSocketInfoInt("Go_Shield_Server_Cache_Time"))
SelfHardMaxCacheSize = GetSocketInfoInt("Go_Shield_Server_DB_Size")
isDebugBigCache = debug
SelfShards = GetSocketInfoInt("Go_Shield_Server_DB_Shards")
if SelfLifeWindow == 0 {
SelfLifeWindow = time.Duration(86400)
}
if SelfHardMaxCacheSize == 0 {
SelfHardMaxCacheSize = 2048
}
if SelfShards == 0 {
SelfShards = 1024
}
config := bigcache.Config{
// number of shards (must be a power of 2)
Shards: SelfShards,
// time after which entry can be evicted
LifeWindow: SelfLifeWindow * time.Second,
// Interval between removing expired entries (clean up).
// If set to <= 0 then no action is performed.
// Setting to < 1 second is counterproductive — bigcache has a one second resolution.
CleanWindow: 5 * time.Minute,
// rps * lifeWindow, used only in initial memory allocation
MaxEntriesInWindow: 1000 * 10 * 60,
// max entry size in bytes, used only in initial memory allocation
MaxEntrySize: 512,
// prints information about additional memory allocation
Verbose: isDebugBigCache,
// cache will not allocate more memory than this limit, value in MB
// if value is reached then the oldest entries can be overridden for the new ones
// 0 value means no size limit
HardMaxCacheSize: SelfHardMaxCacheSize,
// callback fired when the oldest entry is removed because of its expiration time or no space left
// for the new entry, or because delete was called. A bitmask representing the reason will be returned.
// Default value is nil which means no callback and it prevents from unwrapping the oldest entry.
OnRemove: nil,
// OnRemoveWithReason is a callback fired when the oldest entry is removed because of its expiration time or no space left
// for the new entry, or because delete was called. A constant representing the reason will be passed through.
// Default value is nil which means no callback and it prevents from unwrapping the oldest entry.
// Ignored if OnRemove is specified.
OnRemoveWithReason: nil,
}
InMemoryCache, _ = bigcache.NewBigCache(config)
}
func Md5string(str string) string {
h := md5.New()
io.WriteString(h, str)
hashed := hex.EncodeToString(h.Sum(nil))
return hashed
}
func Append(key string, value string) {
InMemoryCache.Append(key, []byte(value))
}
func Fetch(key string) (response *string, error error) {
if value, err := InMemoryCache.Get(key); err == nil {
val := string(value)
if val == "" {
err = errors.New("empty val")
if isDebugBigCache {
log.Printf("Unable to Fetch %s due %s", key, err)
}
return nil, err
}
return &val, nil
} else {
if isDebugBigCache {
log.Printf("Unable to Fetch %s due %s", key, err)
}
return nil, err
}
//return nil
}
func Increment(key string) {
counter, _ := Fetch(key)
if counter == nil {
val := 0
val = val + 1
Append(key, strconv.Itoa(val))
} else {
val, err := strconv.Atoi(*counter)
if err == nil {
val = val + 1
Append(key, strconv.Itoa(val))
}
}
}
func Decrement(key string) {
counter, _ := Fetch(key)
val, err := strconv.Atoi(*counter)
if err == nil {
val = val - 1
if val < 0 {
val = 0
}
Append(key, strconv.Itoa(val))
}
}
func UserAliases(mac string, ipaddr string, ipstrongswan string, isDebugBigCache bool) string {
mac = strings.ToLower(mac)
val := ""
key := ""
if len(mac) > 5 {
key = fmt.Sprintf("%s:alias", mac)
macpath := fmt.Sprintf("/home/artica/UsersMac/Caches/%s", mac)
//val = Get(key, isDebugBigCache)
//if val != "" {
// if val == "NONE" {
// return ""
// }
// sfinl := strings.Split(val, "|")
// if len(sfinl) > 0 {
// return sfinl[0]
// }
// return val
//}
if value, err := InMemoryCache.Get(key); err == nil {
val = string(value)
if val != "" {
if val == "NONE" {
return ""
}
sfinl := strings.Split(val, "|")
if len(sfinl) > 0 {
return sfinl[0]
}
return val
}
}
if _, err := os.Stat(macpath); !os.IsNotExist(err) {
f, err := os.Open(macpath)
if err != nil {
if isDebugBigCache {
log.Printf("error reading %s %s", macpath, err)
}
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
Set(key, scanner.Text(), 600)
sfinl := strings.Split(scanner.Text(), "|")
if len(sfinl) > 0 {
return sfinl[0]
}
return scanner.Text()
}
if err := scanner.Err(); err != nil {
if isDebugBigCache {
log.Printf("error scanning %s %s", macpath, err)
}
}
}
Set(key, "NONE", 600)
if len(ipstrongswan) > 0 {
key = fmt.Sprintf("%s:vpnalias", ipaddr)
//val = Get(key, isDebugBigCache)
//
//if val != "" {
// if val == "NONE" {
// return ""
// }
// return val
//}
if value, err := InMemoryCache.Get(key); err == nil {
val = string(value)
if val != "" {
if val == "NONE" {
return ""
}
return val
}
}
val = StrongSwanAlias(ipaddr, isDebugBigCache)
if val == "" {
Set(key, "NONE", 150)
return ""
}
Set(key, val, 150)
}
key = fmt.Sprintf("%s:alias", ipaddr)
cachepath := fmt.Sprintf("/home/artica/UsersMac/Caches/%s", ipaddr)
//val = Get(key, isDebugBigCache)
//if val != "" {
// if val == "NONE" {
// return ""
// }
// sfinl := strings.Split(val, "|")
// if len(sfinl) > 0 {
// return sfinl[0]
// }
// return val
//}
if value, err := InMemoryCache.Get(key); err == nil {
val = string(value)
if val != "" {
if val == "NONE" {
return ""
}
sfinl := strings.Split(val, "|")
if len(sfinl) > 0 {
return sfinl[0]
}
return val
}
}
if _, err := os.Stat(cachepath); !os.IsNotExist(err) {
f, err := os.Open(cachepath)
if err != nil {
if isDebugBigCache {
log.Printf("error reading %s %s", cachepath, err)
}
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
Set(key, scanner.Text(), 600)
sfinl := strings.Split(scanner.Text(), "|")
if len(sfinl) > 0 {
return sfinl[0]
}
return scanner.Text()
}
if err := scanner.Err(); err != nil {
if isDebugBigCache {
log.Printf("error scanning %s %s", cachepath, err)
}
}
}
}
Set(key, "NONE", 600)
return ""
}
func StrongSwanAlias(ipaddr string, isDebugBigCache bool) string {
//TODO implement this method
//data := GetSocketInfoString("strongSwanClientsArray")
//out, err := gophp.Unserialize([]byte(data))
//
//if err != nil {
// if isDebugBigCache {
// log.Printf("error Unserialize strongSwanClientsArray: ", err)
// }
// return ""
//}
//if mout, ok := out.(map[string]interface{}); ok {
// for _, main_index := range mout {
// subarray := main_index.(map[string]interface{})
// for _, main_index2 := range subarray {
// subarray2 := mout[main_index][main_index2]
// }
// }
//}
return ""
}
func ShieldsFullCache(username string, ipaddr string, mac string, sitename string, method string) string {
sitename = strings.ToLower(sitename)
username = strings.ToLower(username)
method = strings.ToLower(mac)
PrepareCache := []byte(fmt.Sprintf("%s|%s|%s|%s|%s", username, ipaddr, mac, sitename, method))
PrepareCache = []byte(Md5string(string(PrepareCache)))
smd5 := fmt.Sprintf("SHIELD.%s", PrepareCache)
return smd5
}

253
server/internal/handlers.go Executable file

File diff suppressed because one or more lines are too long

122
server/internal/memcached.go Executable file
View File

@ -0,0 +1,122 @@
package internal
import (
"context"
"errors"
"github.com/bradfitz/gomemcache/memcache"
"github.com/go-redis/redis/v8"
"log"
"time"
)
var isDebugMemcached bool
var MC = memcache.New("/var/run/memcached.sock")
var ctxRedis = context.Background()
var rdb *redis.Client
func InitMemcached(debug bool) {
isDebugMemcached = debug
}
func Get(key string) (response string, err error) {
log.Printf("Memcached GET %s", key)
val, err := MC.Get(key)
if err != nil {
if isDebugMemcached {
log.Printf("Memcached Get->Error: %s", err)
}
return "", err
}
if string(val.Value) == "" {
if isDebugMemcached {
log.Printf("Memcached Get->Error: %s", errors.New("empty value"))
}
return "", errors.New("empty value")
}
value := string(val.Value)
return value, nil
}
func Set(key string, value string, ttl int32) {
log.Printf("Memcached SET %s", key)
err := MC.Set(&memcache.Item{Key: key, Value: []byte(value), Expiration: ttl})
if err != nil {
if isDebugMemcached {
log.Printf("Memcached Get->Error: %s", err)
}
//panic(err)
}
}
func Inc(key string, value string) {
if isDebugMemcached {
log.Printf("Memcached Inc %s", key)
}
_, err := Get(key)
if err != nil {
Set(key, "1", 36000)
} else {
MC.Increment(key, 1)
}
}
func redisConnect() bool {
rdb = redis.NewClient(&redis.Options{
Addr: "127.0.0.1:6123",
Password: "", // no password set
DB: 0, // use default DB
})
err := rdb.Set(ctxRedis, "key", "value", 0).Err()
if err != nil {
if isDebugMemcached {
log.Printf("Failed to connect to redis server %s", err)
}
return false
}
return true
}
func RedisGet(key string) string {
if !redisConnect() {
if isDebugMemcached {
log.Printf("Failed to connect to redis server")
}
return ""
}
val, err := rdb.Get(ctxRedis, key).Result()
if err == redis.Nil {
if isDebugMemcached {
log.Printf("key %s does not exist", key)
}
return ""
} else if err != nil {
if isDebugMemcached {
log.Printf("erro getting key %s => %s", key, err)
}
return ""
} else {
return val
}
return ""
}
func RedisSet(key string, val string, ttl time.Duration) bool {
if !redisConnect() {
if isDebugMemcached {
log.Printf("Failed to connect to redis server")
}
return false
}
err := rdb.Set(ctxRedis, key, val, ttl).Err()
if err != nil {
if isDebugMemcached {
log.Printf("erro setting key %s => %s", key, err)
}
return false
}
return true
}

182
server/itchart/intchart.go Executable file
View File

@ -0,0 +1,182 @@
//package itchart
//
//import (
// "encoding/base64"
// "fmt"
// "github.com/techoner/gophp"
// "log"
// "net/netip"
// "server/internal"
// "strconv"
// "strings"
//)
//
//var (
// isDebugITChart bool
// SelfITChartMessage string
// SelfITChartSitename string
// SelfITChartRedirectPage string
// SelfNetworksExcludeLine string
//)
//
//func IntITChart(debug bool) {
// isDebugITChart = debug
// SelfITChartRedirectPage = internal.GetSocketInfoString("ITChartRedirectURL")
// SelfITChartRedirectPage = strings.ToLower(SelfITChartRedirectPage)
// SelfNetworksExcludeLine = internal.GetSocketInfoString("ITChartNetworkExclude")
//}
//
//func ChartThis(ipaddr, mac, username, protocol, sitename string) bool {
// SelfITChartSitename = sitename
// if strings.Index(SelfITChartRedirectPage, sitename) > -1 {
// if isDebugITChart {
// log.Printf("%s: [DEBUG]: <%s> is the redirected page, no sense to block it", ipaddr, sitename)
// }
// return false
// }
// if protocol == "CONNECT" {
// if isDebugITChart {
// log.Printf("%s: %s: [DEBUG] [%s] method excluded, PASS", ipaddr, sitename, protocol)
// }
// return false
// }
// if isNetExcluded(SelfNetworksExcludeLine, ipaddr, mac) {
// log.Printf("%s: [DEBUG] isNetExcluded report True, PASS", ipaddr)
// return false
// }
// keyAccount := findKeyAccount(username, ipaddr, mac)
// if isDebugITChart {
// log.Printf("%s: [DEBUG] [%s]: username=%s ipaddr=%s mac=%s sitename=%s method=%s ->get_itcharts_ids()", sitename, keyAccount, username, ipaddr, mac, sitename, protocol)
// }
//
// itChartIDs := getITChartIDs()
// if len(itChartIDs) == 0 {
// if isDebugITChart {
// log.Printf("%s: [DEBUG] [%s] PASS: No IT Chart available in configuration", sitename, keyAccount)
// }
// return false
// }
// for id, _ := range itChartIDs {
// keyMem := fmt.Sprintf("%s|%s", keyAccount, id)
// keyAD := fmt.Sprintf("itchart.activedirtectory.%s", id)
// keyToError := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s|%s|%s|%s", keyAccount, id, protocol, sitename)))
// timestamp, _ := strconv.Atoi(internal.RedisGet(keyMem))
// if timestamp > 0 {
// continue
// }
// if len(username) > 0 {
// adFilters := internal.RedisGet(keyAD)
// if len(adFilters) > 0 {
// if isDebugITChart {
// log.Printf("%s: [DEBUG] Checking ITCharter AD filters [%s] = %s", keyAccount, keyAD, len(adFilters))
// }
// }
//
// }
//
// }
// return false
//}
//
//func getITChartIDs() map[string]bool {
// //TODO finish it
// results := map[string]bool{}
// data, _ := base64.StdEncoding.DecodeString(internal.RedisGet("itcharts.ids"))
// if len(data) < 3 {
// if isDebugITChart {
// log.Printf("%s: [DEBUG]: get_itcharts_ids no more data [SKIP]", SelfITChartSitename)
// }
// return results
// }
// out, err := gophp.Unserialize([]byte(data))
// if err != nil {
// if isDebugITChart {
// log.Printf("error Unserialize itcharts.ids: ", err)
// }
// return results
// }
// if mout, ok := out.(map[string]interface{}); ok {
// for x, data := range mout {
// results[x] = data.(bool)
// }
// } else {
// if isDebugITChart {
// log.Printf("%s: [DEBUG] ERROR <%s>", SelfITChartSitename, err)
// }
// return results
// }
// if isDebugITChart {
// log.Printf("%s: [DEBUG]: get_itcharts_ids array of %d items", SelfITChartSitename, len(results))
// }
// return results
//}
//
//func findKeyAccount(username, ipaddr, mac string) string {
// if username == "-" {
// username = ""
// }
// if ipaddr == "-" {
// ipaddr = ""
// }
// if ipaddr == "127.0.0.1" {
// ipaddr = ""
// }
// if mac == "-" {
// mac = ""
// }
// if mac == "00:00:00:00:00:00" {
// mac = ""
// }
// if len(username) > 3 {
// return username
// }
// if len(mac) > 3 {
// return mac
// }
// if len(ipaddr) > 3 {
// return ipaddr
// }
// return ""
//}
//
//func isNetExcluded(network, ipaddr, mac string) bool {
// if network == "" {
// if isDebugITChart {
// log.Printf("%s: [DEBUG]: isNetExcluded None, aborting", SelfITChartSitename)
// }
// return false
// }
// if len(network) < 3 {
// if isDebugITChart {
// log.Printf("%s: [DEBUG]: isNetExcluded Not configured, aborting", SelfITChartSitename)
// }
// return false
// }
// net := strings.Split(network, "\n")
// for _, cdir := range net {
// if isDebugITChart {
// log.Printf("%s: [DEBUG]: isNetExcluded checking %s against %s %s", SelfITChartSitename, cdir, ipaddr, mac)
// }
// if mac == cdir {
// return true
// }
// if ipaddr == cdir {
// return true
// }
// network, err := netip.ParsePrefix(cdir)
// if err != nil {
// panic(err)
// }
// ip, err := netip.ParseAddr(ipaddr)
// if err != nil {
// panic(err)
// }
// if network.Contains(ip) {
// if isDebugITChart {
// log.Printf("%s: [DEBUG]: isNetExcluded checking %s matches %s", SelfITChartSitename, cdir, ipaddr)
// }
// return true
// }
// }
// return false
//}

1468
server/main.go Executable file

File diff suppressed because it is too large Load Diff

836
server/shields/shields.go Executable file
View File

@ -0,0 +1,836 @@
package shields
import (
"fmt"
"github.com/d3mondev/resolvermt"
"github.com/techoner/gophp"
"log"
"reflect"
"regexp"
"server/categorization"
"server/internal"
"strconv"
"strings"
"time"
"unicode"
)
var (
SelfKsrnPorn bool
SelfDisableAdvert bool
SelfHatredAndDiscrimination bool
isDebugShields bool
SelfShieldIpaddr string
SelfShieldUsername string
SelfShieldMac string
SelfError string
SelfCategory int
SelfCategoryName string
SelfAction string
SelfSitename string
SelfStartTime time.Time
SelfLocalCache map[string]string
SelfKsrnLicense bool
SelfKsrnEnable bool
SelfQueryIPAddr bool
SelfKSRNEmergency bool
SelfTheShieldLogsQueries bool
SelfDurationText string
SelfHit int
SelfLocalCacheCount int
SelfTheShieldsCguard bool
)
func InitShileds(debub bool) {
SelfKsrnPorn = internal.GetSocketInfoBool("KsrnPornEnable")
SelfDisableAdvert = internal.GetSocketInfoBool("KsrnDisableAdverstising")
SelfHatredAndDiscrimination = internal.GetSocketInfoBool("KsrnHatredEnable")
isDebugShields = debub
SelfKsrnEnable = internal.GetSocketInfoBool("KSRNEnable")
SelfQueryIPAddr = internal.GetSocketInfoBool("KsrnQueryIPAddr")
SelfKSRNEmergency = internal.GetSocketInfoBool("KSRNEmergency")
SelfKsrnLicense = internal.GetSocketInfoBool("KSRN_LICENSE")
SelfTheShieldsCguard = internal.GetSocketInfoBool("TheShieldsCguard")
SelfLocalCache = make(map[string]string)
if internal.GetArticaGoldLicense() {
SelfKsrnLicense = true
}
if isDebugShields {
SelfTheShieldLogsQueries = true
}
}
//TODO Change DNS System
func GetHost(sitename string) string {
resolvers := []string{
categorization.SelfDns1,
categorization.SelfDns2,
}
url := strings.TrimSuffix(sitename, "\n")
domains := []string{
url,
}
client := resolvermt.New(resolvers, 3, 1000, 50)
defer client.Close()
results := client.Resolve(domains, resolvermt.TypeA)
for _, record := range results {
if isDebugShields {
log.Printf("%s: * * * HOST Resolution: [%s] * * *", sitename, record.Answer)
}
return record.Answer
}
return ""
}
func Operate(sitename string) bool {
log.Printf("THE SHIELDS DEBUG MODE IS %t", isDebugShields)
SelfStartTime = time.Now()
SelfError = ""
SelfCategory = 0
SelfAction = ""
SelfSitename = sitename
if categorization.IsArpa(sitename) {
SelfSitename = categorization.SelfStripaddr
if categorization.IsPrivateIp(SelfSitename) {
SelfCategory = 82
SelfCategoryName = categorization.CategoryIntToString(SelfCategory)
return false
}
}
fullCache := fmt.Sprint("SRNRESULTS:%s", sitename)
scacheKey := fmt.Sprint("SRN_CACHE_WHITE:%s", sitename)
//internal.Increment("KSRN_REQUESTS")
internal.Inc("KSRN_REQUESTS", "1")
if isDebugShields {
log.Printf("* * * * * * * * * * * * * * * * O P E R A T E * * * * * * * * * * * * *")
log.Printf("%s ANALYZE...", sitename)
}
memWhite := getCached(sitename)
if memWhite != "" {
SelfError = ""
SelfAction = "WHITELIST"
localCategories(sitename)
SelfCategory, _ = categorization.GetCategories(sitename)
if isDebugShields {
log.Printf("%s [DEBUG]: PASS HIT whitelisted (Cache), aborting %s ", sitename, internal.TimeTrack(SelfStartTime))
}
return false
}
if categorization.AdminWhitelist(sitename, false) {
if isDebugShields {
log.Printf("%s: [DEBUG] MISS whitelisted, aborting", sitename)
}
setCache(scacheKey, "1")
SelfError = ""
SelfAction = "WHITELIST"
localCategories(sitename)
if SelfCategory == 0 {
SelfCategory, _ = categorization.GetCategories(sitename)
}
if isDebugShields {
log.Printf("%s: [DEBUG] MISS whitelisted, aborting %s", sitename, internal.TimeTrack(SelfStartTime))
}
return true
}
if !SelfKsrnLicense {
SelfError = "LICENSE_ERROR"
SelfAction = "PASS"
localCategories(sitename)
if isDebugShields {
log.Printf("%s: [ERROR]: Not a valid license %s", sitename, internal.TimeTrack(SelfStartTime))
}
return false
}
if !SelfKsrnEnable {
SelfError = "DISABLED"
SelfAction = "PASS"
localCategories(sitename)
if isDebugShields {
log.Printf("%s: [ERROR]: Module is Disabled %s", sitename, internal.TimeTrack(SelfStartTime))
}
return false
}
if !SelfQueryIPAddr {
matches, _ := regexp.MatchString("^[0-9\\.]+$", sitename)
if matches {
SelfError = "IPADDR"
SelfAction = "PASS"
localCategories(sitename)
if isDebugShields {
log.Printf("%s: [DEBUG]: is an IP Address %s", sitename, internal.TimeTrack(SelfStartTime))
}
return false
}
}
if SelfKSRNEmergency {
SelfError = "EMERGENCY"
SelfAction = "PASS"
localCategories(sitename)
if isDebugShields {
log.Printf("%s: [DEBUG]: WARNING... Emergency Enabled %s", sitename, internal.TimeTrack(SelfStartTime))
}
return false
}
if categorization.FixedWhitelist(sitename) {
//internal.Append(scacheKey, "1")
setCache(scacheKey, "1")
SelfError = ""
SelfAction = "PASS"
localCategories(sitename)
if SelfCategory == 0 {
SelfCategory, _ = categorization.GetCategories(sitename)
}
if isDebugShields {
log.Printf("%s: [DEBUG]: MISS whitelisted, aborting %s", sitename, internal.TimeTrack(SelfStartTime))
}
return true
}
resultIP := getCached(fullCache)
if resultIP != "" {
if isDebugShields {
log.Printf("%s: [DEBUG]: get_cache(%s) HIT = %s", sitename, fullCache, internal.TimeTrack(SelfStartTime))
}
}
SelfHit = 0
if resultIP == "" {
category := localCategories(sitename)
if isDebugShields {
log.Printf("%s MISS Local category=[%d] %s", sitename, category, internal.TimeTrack(SelfStartTime))
}
if category > 0 {
resultIP = fmt.Sprintf("127.12.%s.1", sitename)
setCache(fullCache, resultIP)
results := understandIP(resultIP)
runStats(sitename)
if isDebugShields {
log.Printf("%s ENGINE=%s category[%d] %s %s after The Shields Query", sitename, SelfAction, SelfCategory, results, internal.TimeTrack(SelfStartTime))
}
}
if isDebugShields {
log.Printf("%s IP=%s", sitename, resultIP)
}
if resultIP == "" {
resultIP = theShieldQuery(sitename)
if isDebugShields {
log.Printf("%s CLOUD --> the_shield_query(%s) = %s", sitename, sitename, resultIP)
}
}
if resultIP == "" {
SelfAction = "PASS"
if isDebugShields {
log.Printf("%s result_ip is None", sitename)
}
return false
}
if isDebugShields {
log.Printf("%s theshield.operate HIT [%s]", sitename, resultIP)
}
setCache(fullCache, resultIP)
} else {
SelfHit = 1
if isDebugShields {
log.Printf("%s theshield.operate HIT [%s]", sitename, resultIP)
}
}
statTime := time.Now()
_ = understandIP(resultIP)
runStats(sitename)
if isDebugShields {
log.Printf("FINAL:%s", internal.TimeTrack(statTime))
}
return true
}
func theShieldQuery(sitename string) string {
statTime := time.Now()
if SelfTheShieldsCguard {
if isDebugShields {
log.Printf("[DEBUG]: --> query_cguard(%s)", sitename)
}
increaseStatsLine()
resultIP := queryCguard(sitename)
if resultIP != nil {
return *resultIP
}
}
encodedPart := encryptUpper(sitename)
searchQuery := fmt.Sprintf("%s.%s", encodedPart, "crdf.artica.center")
if isDebugShields {
log.Printf("[DNS]: %s --> %s %s", sitename, searchQuery, "[QUERY]")
}
increaseStatsLine()
//TODO Change DNS System
resolvers := []string{
categorization.SelfDns1,
categorization.SelfDns2,
}
url := strings.TrimSuffix(searchQuery, "\n")
domains := []string{
url,
}
client := resolvermt.New(resolvers, 3, 1000, 50)
defer client.Close()
results := client.Resolve(domains, resolvermt.TypeA)
for _, record := range results {
if isDebugShields {
log.Printf("DNS %s category=%s MISS shield.query_cloud %s", sitename, record.Answer, internal.TimeTrack(statTime))
}
return record.Answer
}
return ""
}
func encryptUpper(plaintext string) string {
shift := 3
encryption := ""
text := plaintext
text = strings.ToUpper(text)
text = strings.ReplaceAll(text, ".", "chr2")
//fmt.Println(text)
for _, c := range text {
if unicode.IsUpper(c) {
//c_unicode := int(c)
c_index := int(c) - int('A')
new_index := (c_index + shift) % 26
new_unicode := new_index + int('A')
new_character := rune(new_unicode)
//fmt.Printf("%c\n", new_character)
encryption = encryption + string(new_character)
} else {
encryption += string(c)
}
}
return strings.ToLower(encryption)
}
func queryCguard(sitename string) *string {
key := fmt.Sprintf("query_cguard:%s", sitename)
detects := []int{5026, 5066, 5113, 5001, 5058, 5048, 5035, 5096, 5019, 5043, 5045, 5017, 5010, 5002, 5036, 5042, 5005, 5003, 5029, 5030, 5024, 5027, 5107, 5111, 5093, 5033, 5104, 5101, 5114}
category := getCached(key)
if category != "" {
if isDebugShields {
log.Printf("DNS %s category=%s HIT shield.query_cguard", sitename, category)
}
categoryID, _ := strconv.Atoi(category)
if categoryID == 0 {
return nil
}
for _, val := range detects { // Loop
if val == categoryID {
break
result := fmt.Sprintf("127.96.0.%s", category)
return &result
}
}
return nil
}
categoryID := categorization.GetCategoriesCguard(sitename)
if isDebugShields {
log.Printf("DNS %s category=%d MISS shield.query_cguard", sitename, categoryID)
}
setCache(key, string(categoryID))
if categoryID == 0 {
return nil
}
for _, val := range detects { // Loop
if val == categoryID {
break
result := fmt.Sprintf("127.96.0.%s", category)
return &result
}
}
if isDebugShields {
log.Printf("[DEBUG]: --> %s < == %s", sitename, "SKIP")
}
return nil
}
func increaseStatsLine() {
statsKey := fmt.Sprintf("SRNSTATSLINE:%s", internal.GetTimeDelta(10, 1))
//internal.Increment(statsKey)
internal.Inc(statsKey, "1")
}
func runStats(sitename string) bool {
delta := internal.GetTimeDelta(10, 1)
time10mn := internal.GetTimeDelta(10, 2)
if SelfAction == "REAFFECTED" {
return true
}
if SelfAction == "PASS" {
return true
}
if SelfCategory == 0 || SelfCategoryName == "" {
SelfCategory, SelfCategoryName = categorization.GetCategories(sitename)
}
SelfShieldUsername = ""
SelfShieldMac = ""
duration := time.Since(SelfStartTime).Milliseconds()
filename := fmt.Sprintf("/var/log/squid/%s.ksrn", delta)
msg := fmt.Sprintf("%s|%s|%s|%s|%d|%s|%s|%d", time10mn, SelfShieldUsername, SelfShieldIpaddr, SelfShieldMac, SelfCategory, sitename, SelfAction, duration)
internal.Logfile(filename, msg)
internal.Inc("KSRN_DETECTED", "1")
if isDebugShields {
log.Printf("[DETECTED]: From %s [%s] (%s) category: %s (%s) to website %s", SelfShieldUsername, SelfShieldIpaddr, SelfShieldMac, SelfCategoryName, SelfAction, sitename)
}
return true
}
func understandIP(ip string) bool {
sitename := SelfSitename
var matches bool
var rs []string
var re *regexp.Regexp
if isDebugShields {
log.Printf("%s [%s]: Check Porn ?: %t", sitename, ip, SelfKsrnPorn)
}
re = regexp.MustCompile("^127\\.96\\.0\\.([0-9]+)")
matches = re.MatchString(ip)
if matches {
if isDebugShields {
log.Printf("%s: [DEBUG] [%s] CGuard detected", sitename, ip)
}
rs = re.FindStringSubmatch(ip)
sporn := []int{5113, 5001, 5058, 5048}
shaines := []int{5033, 5104, 5101, 5114}
resultCat, _ := strconv.Atoi(rs[1])
if SelfDisableAdvert {
if resultCat == 5026 || resultCat == 5066 {
if isDebugShields {
log.Printf("%s: [DEBUG] [%d] Exclude (Privacy Shield disabled)", sitename, resultCat)
}
SelfAction = "PASS"
return true
}
}
if !SelfKsrnPorn {
for _, val := range sporn { // Loop
if val == resultCat {
SelfAction = "PASS"
if isDebugShields {
log.Printf("%s: [DEBUG] [%d] Exclude (Porn Shield disabled)", sitename, resultCat)
}
break
return true
}
}
}
if !SelfHatredAndDiscrimination {
for _, val := range shaines { // Loop
if val == resultCat {
SelfAction = "PASS"
if isDebugShields {
log.Printf("%s: [DEBUG] [%d] Exclude (Hate and discrimination)", sitename, resultCat)
}
break
return true
}
}
}
SelfAction = "CGUARD"
return true
}
re = regexp.MustCompile("127\\.12\\.([0-9]+)\\.1")
matches = re.MatchString(ip)
if matches {
SelfAction = "PASS"
badCarz := []int{6, 7, 10, 72, 92, 105, 111, 135, 132, 109, 5, 143}
hatred := []int{130, 148, 149, 150, 140}
rs = re.FindStringSubmatch(ip)
resultCat, _ := strconv.Atoi(rs[1])
if SelfCategory == 0 {
SelfCategory, SelfCategoryName = categorization.GetCategories(sitename)
if isDebugShields {
log.Printf("%s category==0 ??? with [%s] retreive it ! -> %d", sitename, ip, SelfCategory)
}
}
if isDebugShields {
log.Printf("%s [%d]: ARTICA", sitename, resultCat)
}
if SelfCategory > 0 {
if !SelfKsrnPorn {
if resultCat == 109 || resultCat == 132 {
if isDebugShields {
log.Printf("%s [%d]: ARTICA PORN EXCLUDE", sitename, resultCat)
}
SelfAction = "PASS"
if isDebugShields {
log.Printf("%s: [DEBUG] [%d] Exclude (Porn Shield disabled)", sitename, resultCat)
}
return true
}
}
if SelfDisableAdvert {
if resultCat == 5 || resultCat == 143 {
if isDebugShields {
log.Printf("%s: [DEBUG] [%d] Exclude (Privacy Shield disabled)", sitename, resultCat)
}
SelfAction = "PASS"
return true
}
}
if !SelfHatredAndDiscrimination {
for _, val := range hatred { // Loop
if val == resultCat {
SelfAction = "PASS"
if isDebugShields {
log.Printf("%s: [DEBUG] [%d] Exclude (Hate and discrimination)", sitename, resultCat)
}
break
return true
}
}
}
for _, val := range badCarz { // Loop
if val == resultCat {
SelfAction = "ARTICA"
if isDebugShields {
log.Printf("%s [%d]: ARTICA DETECTED", sitename, resultCat)
}
break
return true
}
}
}
return true
}
if ip == "127.10.1.0" {
SelfCategory = 92
SelfAction = "MALWAREURL_MALWARES"
return true
}
if ip == "127.10.2.0" {
SelfCategory = 105
SelfAction = "MALWAREURL_PHISHING"
return true
}
re = regexp.MustCompile("127\\.10\\.1\\.([0-9]+)")
matches = re.MatchString(ip)
if matches {
rs = re.FindStringSubmatch(ip)
SelfCategory, _ = strconv.Atoi(rs[1])
SelfAction = "CLOUDFLARE"
return true
}
re = regexp.MustCompile("127\\.10\\.2\\.([0-9]+)")
matches = re.MatchString(ip)
if matches {
rs = re.FindStringSubmatch(ip)
SelfCategory, _ = strconv.Atoi(rs[1])
SelfAction = "CLOUDFLARE"
return true
}
if ip == "127.3.1.0" {
SelfCategory, _ = strconv.Atoi(rs[1])
SelfAction = "CLOUDFLARE"
return true
}
if ip == "127.3.2.0" {
SelfCategory, _ = strconv.Atoi(rs[1])
SelfAction = "CLOUDFLARE"
return true
}
re = regexp.MustCompile("127\\.3\\.1\\.([0-9]+)")
matches = re.MatchString(ip)
if matches {
rs = re.FindStringSubmatch(ip)
SelfCategory, _ = strconv.Atoi(rs[1])
SelfAction = "CLOUDFLARE"
return true
}
re = regexp.MustCompile("127\\.3\\.2\\.([0-9]+)")
matches = re.MatchString(ip)
if matches {
rs = re.FindStringSubmatch(ip)
SelfCategory, _ = strconv.Atoi(rs[1])
SelfAction = "REAFFECTED"
return true
}
if ip == "127.4.0.0" {
SelfCategory = 92
SelfAction = "GENERIC"
return true
}
re = regexp.MustCompile("127\\.4\\.0\\.([0-9]+)")
matches = re.MatchString(ip)
if matches {
rs = re.FindStringSubmatch(ip)
SelfCategory, _ = strconv.Atoi(rs[1])
SelfAction = "GENERIC"
return true
}
if ip == "127.2.0.0" {
SelfCategory = 92
SelfAction = "GOOGLE"
return true
}
re = regexp.MustCompile("127\\.2\\.0\\.([0-9]+)")
matches = re.MatchString(ip)
if matches {
rs = re.FindStringSubmatch(ip)
SelfCategory, _ = strconv.Atoi(rs[1])
SelfAction = "GOOGLE"
return true
}
re = regexp.MustCompile("^127\\.254\\.0\\.([0-9]+)$")
matches = re.MatchString(ip)
if matches {
rs = re.FindStringSubmatch(ip)
SelfCategory, _ = strconv.Atoi(rs[1])
SelfAction = "KASPERSKY"
return true
}
if ip == "127.5.0.0" {
if SelfDisableAdvert {
SelfCategory = 5
SelfAction = "PASS"
return true
}
SelfCategory = 5
SelfAction = "ADGUARD"
return true
}
re = regexp.MustCompile("^127\\.5\\.0\\.([0-9]+)$")
matches = re.MatchString(ip)
if matches {
rs = re.FindStringSubmatch(ip)
category, _ := strconv.Atoi(rs[1])
if SelfDisableAdvert {
if category == 5 || category == 143 {
SelfCategory = 5
SelfAction = "PASS"
return true
}
}
SelfCategory = category
SelfAction = "ADGUARD"
return true
}
if ip == "127.253.0.0" {
SelfCategory = 92
SelfAction = "QUAD9"
return true
}
re = regexp.MustCompile("^127\\.253\\.0\\.([0-9]+)$")
matches = re.MatchString(ip)
if matches {
rs = re.FindStringSubmatch(ip)
SelfCategory, _ = strconv.Atoi(rs[1])
SelfAction = "ADGUARD"
return true
}
re = regexp.MustCompile("^0\\.0\\.0\\.([0-9]+)$")
matches = re.MatchString(ip)
if matches {
rs = re.FindStringSubmatch(ip)
SelfCategory, _ = strconv.Atoi(rs[1])
SelfAction = "PASS"
return true
}
SelfAction = "PASS"
return false
}
func getCached(domain string) string {
if _, ok := SelfLocalCache[domain]; ok {
return SelfLocalCache[domain]
}
smd5 := fmt.Sprint("SHIELD.class.%s", internal.Md5string(domain))
if val, _ := internal.Fetch(smd5); val != nil {
str := *val
return str
}
return ""
}
func setCache(domain string, category string) {
SelfLocalCache[domain] = category
SelfLocalCacheCount = SelfLocalCacheCount + 1
smd5 := fmt.Sprintf("SHIELD.class.%s", internal.Md5string(domain))
internal.Append(smd5, category)
if SelfLocalCacheCount > 1500 {
SelfLocalCache = make(map[string]string)
SelfLocalCacheCount = 0
}
}
func localCategories(sitename string) int {
if len(sitename) == 0 {
return 0
}
category, _ := categorization.GetCategories(sitename)
SelfCategory = category
if SelfCategory == 0 {
return 0
}
return SelfCategory
//TODO Confirm rest of func
}
func WriteStats(category int, sitename string, provider string, duration int) {
delta := internal.GetTimeDelta(10, 1)
time10mn := internal.GetTimeDelta(10, 2)
filename := fmt.Sprintf("/var/log/squid/%s.ksrn", delta)
msg := fmt.Sprintf("%s|%s|%s|%s|%d|%s|%s|%d", time10mn, SelfShieldUsername, SelfShieldIpaddr, SelfShieldMac, category, sitename, provider, duration)
internal.Logfile(filename, msg)
}
func CountUsers() {
if len(SelfShieldIpaddr) == 0 {
if isDebugShields {
log.Printf("SelfShieldIpaddr null")
}
return
}
if SelfShieldIpaddr == "127.0.0.1" {
log.Printf("SelfShieldUsername is 127.0.0.1")
return
}
time10min := internal.GetTimeDelta(10, 2)
time10min = strings.ReplaceAll(time10min, " ", "_")
results := map[string]map[string]int{}
//results["IPADDR"] = map[string]int{}
//results["mac"] = map[string]int{}
//results["username"] = map[string]int{}
skey := fmt.Sprintf("CountUsers.%s", time10min)
if isDebugShields {
log.Printf("%s [CountUsers]: %s", time10min, skey)
}
var cc int
if val, err := internal.Get(skey); err == nil {
mount, err := gophp.Unserialize([]byte(val))
if err != nil {
if isDebugShields {
log.Printf("[CountUsers]: Failed to unserialize: ", err)
results = make(map[string]map[string]int)
}
}
log.Printf("Array is %v", mount)
if dataList, ok := mount.(map[string]interface{}); ok {
for x, data := range dataList {
if reflect.ValueOf(data).Len() == 0 {
continue
}
for k, v := range data.(map[string]interface{}) {
if x == "IPADDR" {
if _, ok := results["IPADDR"]; !ok {
if isDebugShields {
log.Printf("%s [CountUsers]: creating IPADDR key", time10min)
}
results["IPADDR"] = map[string]int{}
}
}
if x == "mac" {
if _, ok := results["mac"]; !ok {
if isDebugShields {
log.Printf("%s [CountUsers]: creating Mac key", time10min)
}
results["mac"] = map[string]int{}
}
}
if x == "username" {
if _, ok := results["username"]; !ok {
if isDebugShields {
log.Printf("%s [CountUsers]: creating Username key", time10min)
}
results["username"] = map[string]int{}
}
}
results[x][k] = v.(int)
}
}
} else {
log.Printf("[CountUsers]: Failed to map Array: ", err)
results = make(map[string]map[string]int)
}
} else {
results = make(map[string]map[string]int)
}
if _, ok := results["IPADDR"]; !ok {
if isDebugShields {
log.Printf("%s [CountUsers]: creating IPADDR key", time10min)
}
results["IPADDR"] = map[string]int{}
}
if _, ok := results["IPADDR"][SelfShieldIpaddr]; !ok {
cc = 1
results["IPADDR"][SelfShieldIpaddr] = cc
} else {
cc = results["IPADDR"][SelfShieldIpaddr]
cc = cc + 1
results["IPADDR"][SelfShieldIpaddr] = cc
}
if isDebugShields {
log.Printf("%s [CountUsers]: ipaddr=%s count=%d", time10min, SelfShieldIpaddr, cc)
}
if len(SelfShieldUsername) > 1 {
if _, ok := results["username"]; !ok {
if isDebugShields {
log.Printf("%s [CountUsers]: creating Username key", time10min)
}
results["username"] = map[string]int{}
}
if _, ok := results["username"][SelfShieldUsername]; !ok {
cc = 1
results["username"][SelfShieldUsername] = cc
} else {
cc = results["username"][SelfShieldUsername]
cc = cc + 1
results["username"][SelfShieldUsername] = cc
}
if isDebugShields {
log.Printf("%s [CountUsers]: username=%s count=%d", time10min, SelfShieldUsername, cc)
}
}
if len(SelfShieldMac) > 0 {
if _, ok := results["mac"]; !ok {
if isDebugShields {
log.Printf("%s [CountUsers]: creating Mac key", time10min)
}
results["mac"] = map[string]int{}
}
if _, ok := results["mac"][SelfShieldMac]; !ok {
cc = 1
results["mac"][SelfShieldMac] = cc
} else {
cc = results["mac"][SelfShieldMac]
cc = cc + 1
results["mac"][SelfShieldMac] = cc
}
if isDebugShields {
log.Printf("%s [CountUsers]: mac=%s count=%d", time10min, SelfShieldMac, cc)
}
}
out, _ := gophp.Serialize(results)
internal.Set(skey, string(out), 3600)
if isDebugShields {
log.Printf("%s [CountUsers]: %s SAVED SUCCESS", time10min, skey)
}
}

578
server/ufdbguard/ufdbguard.go Executable file
View File

@ -0,0 +1,578 @@
package ufdbguard
import (
"bufio"
"encoding/binary"
"errors"
"fmt"
"log"
"net"
"net/url"
"os"
"regexp"
"server/categorization"
"server/internal"
"strconv"
"strings"
"time"
)
var (
isDebugUfdbguard bool
SelfUfdbGuardMaxUrisize int
SelfFinalRedirdectCode int
SelfFinalRedirectUrl string
SelfRedirectKey string
SelfProxyProto string
SelfClientMac string
SelfMimik bool
SelfWebfilterRuleName string
SelfIsSSNI bool
SelfRemoteIP string
SelfRemotePort int
SelfUseRemoteUfdbguardService bool
SelfSquidGuardRedirectHTTPCode int
SelfSquidGuardWebUseExternalUri int
SelfSquidGuardWebExternalUri string
SelfSquidGuardWebExternalUriSSL string
SelfHttps bool
SelfUfdbGuardWebFilteringCacheTime int
SelfCached bool
SelfInactiveService bool
SelfUfdbgclientSockTimeOut time.Duration
SelfCategory int
SelfWebfilteringToken string
SelfRuleID int
SelfCategoryName string
SelfToken string
)
func InitUfdbguard(debug bool) {
//Self := &UFDBDefaultVars{}
//log.SetFlags(log.LstdFlags | log.Lshortfile)
//if _slog, err := syslog.New(syslog.LOG_DEBUG, "go-shield-connector-ufdb"); err == nil {
// log.SetOutput(_slog)
//}
SelfRemoteIP = internal.GetSocketInfoString("PythonUfdbServer")
SelfRemotePort = internal.GetSocketInfoInt("PythonUfdbPort")
SelfUseRemoteUfdbguardService = internal.GetSocketInfoBool("UseRemoteUfdbguardService")
SelfSquidGuardRedirectHTTPCode = internal.GetSocketInfoInt("SquidGuardRedirectHTTPCode")
SelfUfdbGuardMaxUrisize = internal.GetSocketInfoInt("UfdbGuardMaxUrisize")
SelfSquidGuardWebUseExternalUri = internal.GetSocketInfoInt("SquidGuardWebUseExternalUri")
SelfSquidGuardWebExternalUri = internal.GetSocketInfoString("SquidGuardWebExternalUri")
SelfSquidGuardWebExternalUriSSL = internal.GetSocketInfoString("SquidGuardWebExternalUriSSL")
SelfUfdbGuardWebFilteringCacheTime = internal.GetSocketInfoInt("UfdbGuardWebFilteringCacheTime")
SelfUfdbgclientSockTimeOut = time.Duration(internal.GetSocketInfoInt("UfdbgclientSockTimeOut")) * time.Second
if SelfUfdbgclientSockTimeOut == 0 {
SelfUfdbgclientSockTimeOut = time.Duration(120) * time.Second
}
if SelfUfdbGuardWebFilteringCacheTime == 0 {
SelfUfdbGuardWebFilteringCacheTime = 300
}
if SelfSquidGuardRedirectHTTPCode < 300 {
SelfSquidGuardRedirectHTTPCode = 302
}
if SelfUfdbGuardMaxUrisize == 0 {
SelfUfdbGuardMaxUrisize = 640
}
isDebugUfdbguard = debug
isBumped()
if !SelfUseRemoteUfdbguardService {
checkLocalConfig()
if SelfRemoteIP == "all" {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: Warning, unable to found the remote TCP Addr config, assume 127.0.0.1")
}
SelfRemoteIP = "127.0.0.1"
}
if len(SelfRemoteIP) == 0 {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: Warning, unable to found the remote TCP Addr config, assume 127.0.0.1")
}
SelfRemoteIP = "127.0.0.1"
}
if SelfRemotePort == 0 {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: Warning, unable to found the remote port config, assume 3977 port")
}
SelfRemotePort = 3977
}
}
if SelfRemotePort > 0 {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: Redirect Code..............: %d", SelfSquidGuardRedirectHTTPCode)
log.Printf("[UFDB_CLASS]: Connect to.................: ufdb://%s:%d", SelfRemoteIP, SelfRemotePort)
log.Printf("[UFDB_CLASS]: SelfSquidGuardWebUseExternalUri: %d", SelfSquidGuardWebUseExternalUri)
log.Printf("[UFDB_CLASS]: SelfSquidGuardWebExternalUri...: %s", SelfSquidGuardWebExternalUri)
log.Printf("[UFDB_CLASS]: SelfSquidGuardWebExternalUriSSL: %s", SelfSquidGuardWebExternalUriSSL)
log.Printf("[UFDB_CLASS]: Listen port: %s:%d", SelfRemoteIP, SelfRemotePort)
if SelfMimik {
log.Printf("[UFDB_CLASS]:MIMIK = %t", SelfMimik)
}
}
}
}
func isBumped() {
if _, err := os.Stat("/etc/squid3/listen_ports.conf"); errors.Is(err, os.ErrNotExist) {
if isDebugUfdbguard {
log.Printf("/etc/squid3/listen_ports.conf not exit: ", err)
}
return
}
f, err := os.Open("/etc/squid3/listen_ports.conf")
if err != nil {
if isDebugUfdbguard {
log.Printf("error reading /etc/squid3/listen_ports.conf: ", err)
}
return
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
reSSLBump := regexp.MustCompile("^http_port.*?ssl-bump")
if reSSLBump.MatchString(scanner.Text()) {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]:MIMIK Found SSL port in proxy configuration")
}
SelfMimik = true
return
}
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]:MIMIK * not * Found SSL port in proxy configuration")
}
}
if err := scanner.Err(); err != nil {
if isDebugUfdbguard {
log.Printf("error scanning /etc/squid3/listen_ports.conf: ", err)
}
return
}
}
func checkLocalConfig() {
if _, err := os.Stat("/etc/squid3/ufdbGuard.conf"); errors.Is(err, os.ErrNotExist) {
if isDebugUfdbguard {
log.Printf("/etc/squid3/ufdbGuard.conf not exit: ", err)
}
return
}
f, err := os.Open("/etc/squid3/ufdbGuard.conf")
if err != nil {
if isDebugUfdbguard {
log.Printf("error reading /etc/squid3/ufdbGuard.conf: ", err)
}
return
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
reInterface := regexp.MustCompile("^interface\\s+(.+)")
if reInterface.MatchString(scanner.Text()) {
rs := reInterface.FindStringSubmatch(scanner.Text())
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: Found Interface %s in ufdbGuard.conf", rs[1])
}
SelfRemoteIP = rs[1]
if SelfRemoteIP == "all" {
SelfRemoteIP = "127.0.0.1"
}
}
rePort := regexp.MustCompile("^port\\s+([0-9]+)")
if rePort.MatchString(scanner.Text()) {
rs := rePort.FindStringSubmatch(scanner.Text())
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: Found Port %s in ufdbGuard.conf", rs[1])
}
SelfRemotePort, _ = strconv.Atoi(rs[1])
}
}
if err := scanner.Err(); err != nil {
if isDebugUfdbguard {
log.Printf("error scanning /etc/squid3/ufdbGuard.conf: ", err)
}
return
}
}
func Process(proxyUrl string, urlDomain string, clientIp string, clientHostname string, username string, clientMacAddr string, proxyIP string, proxyPort int) bool {
if isDebugUfdbguard {
log.Printf("Starting UFDB Process")
}
sourceUrl := proxyUrl
categoryName := "Unknown"
toUfdbCdir := ""
toUfdb := ""
proto := ""
cdirToCheck := ""
SelfCategoryName = categoryName
SelfToken = ""
var Tokens []string
if len(username) == 0 {
username = "-"
}
if len(clientHostname) == 0 {
clientHostname = "-"
}
if len(proxyIP) == 0 {
proxyIP = "127.0.0.1"
}
if proxyPort == 0 {
proxyPort = 3128
}
matches, _ := regexp.MatchString("\\/ufdbguard\\.php\\?rule-id=[0-9]+", proxyUrl)
if matches {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: [CLIENT]: Loop to Web-filtering error page")
}
return false
}
if checkIPAddressType(urlDomain, isDebugUfdbguard) {
re := regexp.MustCompile("^([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)")
if re.MatchString(urlDomain) {
rs := re.FindStringSubmatch(urlDomain)
cdirToCheck := rs[1] + "." + rs[2] + "." + rs[3] + ".cdir"
toUfdbCdir = fmt.Sprintf("http://%s %s/%s %s GET myip=%s myport=%s\n", cdirToCheck, clientIp, clientHostname, username, proxyIP, strconv.Itoa(proxyPort))
}
ip2LongDomain := binary.BigEndian.Uint32(net.ParseIP(urlDomain)[12:16])
newDomain := strconv.FormatUint(uint64(ip2LongDomain), 10) + ".addr"
proxyUrl = strings.ReplaceAll(proxyUrl, urlDomain, newDomain)
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: [CLIENT] replace [' + %s + '] to [' + %s + ']:", urlDomain, newDomain)
}
SelfProxyProto = "GET"
}
proxyUrl = strings.ReplaceAll(proxyUrl, "https", "http")
proxyUrl = strings.ReplaceAll(proxyUrl, ":443", "")
if strings.Index(proxyUrl, "http://") == -1 {
proto = "http://"
}
if SelfUfdbGuardMaxUrisize == 0 {
SelfUfdbGuardMaxUrisize = 640
}
if len(proxyUrl) > SelfUfdbGuardMaxUrisize {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: [CLIENT] ALERT!...: URL %s exceed %d bytes, cut it!", urlDomain, SelfUfdbGuardMaxUrisize)
}
proxyUrl = proxyUrl[0:SelfUfdbGuardMaxUrisize] + "..."
}
if len(toUfdbCdir) > 0 {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: [CLIENT] Pass to Web-Filtering service (CDIR)")
}
SelfClientMac = clientMacAddr
if sendToUfdb(toUfdbCdir, sourceUrl, clientIp, username, cdirToCheck) {
categoryName = "Unknown"
finalRedirdectCode := SelfFinalRedirdectCode
finalRedirectUrl := SelfFinalRedirectUrl
finalRedirectKey := SelfRedirectKey
category := SelfCategory
if category > 0 {
categoryName = categorization.CategoryIntToString(category)
SelfCategoryName = categoryName
}
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: SelfCategory %d Name: %s", category, categoryName)
log.Printf("[UFDB_CLASS]: [CLIENT] CATEGORY=%d", SelfCategory)
}
ap1 := fmt.Sprintf("status=%s %s=%s", finalRedirdectCode, finalRedirectKey, finalRedirectUrl)
Tokens = append(Tokens, ap1)
Tokens = append(Tokens, "shieldsblock=yes")
Tokens = append(Tokens, SelfWebfilteringToken)
ap2 := fmt.Sprintf("category=%s category-name=%s clog=cinfo:%s-%s;", strconv.Itoa(category), categoryName, strconv.Itoa(category), categoryName)
Tokens = append(Tokens, ap2)
SelfToken = strings.Join(Tokens, " ")
return true
}
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: FATAL! Exception while requesting CDIR to Web-Filtering Engine service")
}
return false
}
toUfdb = fmt.Sprintf("%s%s %s/%s %s GET myip=%s myport=%s\n", proto, proxyUrl, clientIp, clientHostname, username, proxyIP, strconv.Itoa(proxyPort))
if sendToUfdb(toUfdb, sourceUrl, clientIp, username, clientHostname) {
category := SelfCategory
if category > 0 {
categoryName = categorization.CategoryIntToString(category)
SelfCategoryName = categoryName
}
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: SelfCategory %d Name: %s", category, categoryName)
}
return true
}
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: FATAL! Exception while requesting Web-Filtering Engine service")
}
return false
}
func sendToUfdb(query string, sourceUrl string, clientIp string, uid string, hostname string) bool {
if isDebugUfdbguard {
log.Printf("Starting SentToUfdb")
}
connected := false
redirection := ""
key := "url"
categoryFound := ""
SelfRuleID = 0
SelfWebfilterRuleName = ""
response := ""
var matches bool
matches, _ = regexp.MatchString("\\s+CONNECT\\s+", query)
if matches {
connected = true
}
if SelfProxyProto == "CONNECT" {
connected = true
}
matches, _ = regexp.MatchString("^([0-9\\.]+)$", hostname)
if !matches {
SelfIsSSNI = true
}
//To Improve Later
if SelfMimik {
if SelfHttps {
if !SelfIsSSNI {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: %s: MIMIK but SNI not set, return false", hostname)
log.Printf("[UFDB_CLASS]: OK: PASS")
return false
}
}
}
}
if connected {
if SelfMimik {
matches, _ = regexp.MatchString("^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])$", hostname)
if matches {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: [%s]:IPv4 Connect received, but mimiked proxy, waiting bumped session..", hostname)
log.Printf("[UFDB_CLASS]: OK: PASS")
}
return false
}
matches, _ = regexp.MatchString("^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])$", hostname)
if matches {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: [%s]:IPv6 Connect received, but mimiked proxy, waiting bumped session..", hostname)
log.Printf("[UFDB_CLASS]: OK: PASS")
}
return false
}
}
}
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS][222]: query: [%s]", strings.TrimSpace(query))
}
SelfCached = false
md5query := internal.Md5string("UFDBCACHE_" + strings.TrimSpace(query))
if SelfUfdbGuardWebFilteringCacheTime > 1 {
//val, err := internal.MC.Get(md5query)
//if err != nil {
// if isDebugUfdbguard {
// log.Printf("Error Getting MD5 from memcache: %s", err)
// }
// panic(err)
//}
//if val != nil {
// SelfCached = true
// response = string(val.Value)
//
//}
if val, err := internal.Fetch(md5query); val != nil {
SelfCached = true
response = *val
} else {
if isDebugUfdbguard {
log.Printf("Error Getting MD5 from in memory cache: %s", err)
}
}
}
if !SelfCached {
response = sendSocket(query)
if isDebugUfdbguard {
log.Printf("####### RESPONSE FROM UFDB WITH VAL %s##############", response)
}
} else {
if isDebugUfdbguard {
log.Printf("####### RESPONSE FROM CACHE WITH VAL %s##############", response)
}
}
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS][360]: response: %s", response)
}
if SelfInactiveService {
return false
}
if response == "OK" {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: OK: PASS")
}
if !SelfCached {
if SelfUfdbGuardWebFilteringCacheTime > 1 {
//internal.MC.Set(&memcache.Item{key: md5query, Value: []byte(response), Expiration: int32(SelfUfdbGuardWebFilteringCacheTime)})
internal.Append(md5query, response)
}
}
return false
}
if len(response) == 0 {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS][238]: UNKNOWN: \"PASS\"")
}
return false
}
if !SelfCached {
if SelfUfdbGuardWebFilteringCacheTime > 1 {
//internal.MC.Set(&memcache.Item{key: md5query, Value: []byte(response), Expiration: int32(SelfUfdbGuardWebFilteringCacheTime)})
internal.Append(md5query, response)
}
}
re := regexp.MustCompile("rewrite-url=\"(.*?)\"")
matches = re.MatchString(response)
key = "rewrite"
rs := re.FindStringSubmatch(response)
if !matches {
re2 := regexp.MustCompile("url=\"(.*?)\"")
matches = re2.MatchString(response)
key = "url"
rs = re2.FindStringSubmatch(response)
}
if matches {
redirection = rs[1]
}
if len(redirection) == 0 {
redirection = response
}
redirection = strings.ReplaceAll(redirection, "??", "?")
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS][297]: redirection = %s (299)", redirection)
}
RedirectionSource := redirection
re3 := regexp.MustCompile("rule-id=([0-9]+).*?targetgroup=(.+?)&")
matches = re3.MatchString(RedirectionSource)
if matches {
rs = re3.FindStringSubmatch(RedirectionSource)
categoryFound = rs[2]
categoryFound = strings.ReplaceAll(categoryFound, "P", "")
SelfRuleID, _ = strconv.Atoi(rs[1])
}
re4 := regexp.MustCompile("clientgroup=(.+?)&")
matches = re4.MatchString(RedirectionSource)
if matches {
rs = re4.FindStringSubmatch(RedirectionSource)
SelfWebfilterRuleName = rs[1]
}
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: categoryFound = %s ruleid=%d", categoryFound, SelfRuleID)
}
if strings.Index(redirection, "=%a") > 0 {
redirection = strings.ReplaceAll(redirection, "clientaddr=%a", "clientaddr="+clientIp)
}
if strings.Index(redirection, "=%i") > 0 {
redirection = strings.ReplaceAll(redirection, "clientuser=%i", "clientuser="+uid)
}
if strings.Index(redirection, "=%u") > 0 {
redirection = strings.ReplaceAll(redirection, "url=%u", "url="+url.PathEscape(sourceUrl))
}
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: redirection %s", redirection)
}
redirection = strings.ReplaceAll(redirection, "\"", "")
SelfFinalRedirectUrl = redirection
SelfRedirectKey = key
SelfCategory, _ = strconv.Atoi(categoryFound)
SelfWebfilteringToken = fmt.Sprintf("webfiltering=block,%s,%s srcurl=\"%s\"", strconv.Itoa(SelfRuleID), categoryFound, url.PathEscape(sourceUrl))
return true
}
func sendSocket(query string) string {
SelfInactiveService = false
response := ""
if SelfRemotePort == 0 {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: Configuration Error, no port set... Aborting!")
}
return ""
}
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: Send to service %s", query)
}
d := net.Dialer{Timeout: SelfUfdbgclientSockTimeOut}
conn, err := d.Dial("tcp", SelfRemoteIP+":"+strconv.Itoa(SelfRemotePort))
if err != nil {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: Connection Error: Unable to connect to %s %d ERROR: %s", SelfRemoteIP, SelfRemotePort, err)
}
return ""
}
fmt.Fprintf(conn, query+"\n")
message, errB := bufio.NewReader(conn).ReadString('\n')
if errB != nil {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: Connection Error: Unable to receive data from %s %d ERROR: %s", SelfRemoteIP, SelfRemotePort, errB)
}
return ""
}
response = strings.TrimSpace(message)
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]: RESPONSE: %s", response)
}
if strings.Index(response, "?loading-database=yes") == 0 {
SelfInactiveService = true
}
if strings.Index(response, "?fatalerror=yes") == 0 {
SelfInactiveService = true
}
if SelfInactiveService {
if isDebugUfdbguard {
log.Printf("[UFDB_CLASS]:FATAL Error Load-database or Web-Filtering error!!")
}
}
return response
}
func checkIPAddressType(ip string, isDebugUfdbguard bool) bool {
if net.ParseIP(ip) == nil {
if isDebugUfdbguard {
log.Printf("Invalid IP Address: %s\n", ip)
}
return false
}
for i := 0; i < len(ip); i++ {
switch ip[i] {
case '.':
if isDebugUfdbguard {
log.Printf("Given IP Address %s is IPV4 type\n", ip)
}
return true
case ':':
if isDebugUfdbguard {
log.Printf("Given IP Address %s is IPV6 type\n", ip)
}
return true
}
}
return false
}