first commit
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/pquerna/otp/totp"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
// Application
|
||||
AppName string `json:"app_name"`
|
||||
|
||||
// Authentication
|
||||
Username string `json:"username"`
|
||||
HashedPass string `json:"hashed_password"`
|
||||
MFASecret string `json:"mfa_secret"`
|
||||
SessionTimeoutMins int `json:"session_timeout_minutes"`
|
||||
|
||||
// Server
|
||||
Port string `json:"port"`
|
||||
BindAddr string `json:"bind_address"`
|
||||
|
||||
// Blocklist settings
|
||||
UpdateDelay int `json:"update_delay_days"`
|
||||
CheckInterval int `json:"check_interval_seconds"`
|
||||
|
||||
// File paths
|
||||
PidFile string `json:"pid_file"`
|
||||
ProcessName string `json:"process_name"`
|
||||
TmpFile string `json:"tmp_file"`
|
||||
LastUpdateFile string `json:"last_update_file"`
|
||||
URLFileList string `json:"url_file_list"`
|
||||
BlocklistFile string `json:"blocklist_file"`
|
||||
RemoveFile string `json:"remove_file"`
|
||||
MergedListTmp string `json:"merged_list_tmp"`
|
||||
|
||||
// Default blocklist URLs
|
||||
DefaultURLs []string `json:"default_urls"`
|
||||
}
|
||||
|
||||
var (
|
||||
config Config
|
||||
configFile = "config.json"
|
||||
configMu sync.RWMutex
|
||||
)
|
||||
|
||||
func getDefaultConfig() Config {
|
||||
return Config{
|
||||
AppName: "Unifi Blocklist Manager",
|
||||
Username: "admin",
|
||||
HashedPass: "", // Will be set with hashed password
|
||||
MFASecret: "",
|
||||
SessionTimeoutMins: 60, // 1 hour default
|
||||
Port: "8080",
|
||||
BindAddr: "0.0.0.0",
|
||||
UpdateDelay: 3,
|
||||
CheckInterval: 5,
|
||||
PidFile: "/tmp/coredns_last.pid",
|
||||
ProcessName: "coredns",
|
||||
TmpFile: "/sdcard1/combined-blocklist.txt",
|
||||
LastUpdateFile: "/sdcard1/last_update.txt",
|
||||
URLFileList: "/sdcard1/urllist.txt",
|
||||
BlocklistFile: "/run/utm/domain_list/domainlist_0.list",
|
||||
RemoveFile: "/run/utm/domain_list/domainlist_1.list",
|
||||
MergedListTmp: "/tmp/mergedlist.txt",
|
||||
DefaultURLs: []string{
|
||||
"https://adguardteam.github.io/HostlistsRegistry/assets/filter_27.txt",
|
||||
"https://adguardteam.github.io/HostlistsRegistry/assets/filter_49.txt",
|
||||
"https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt",
|
||||
"https://adguardteam.github.io/HostlistsRegistry/assets/filter_42.txt",
|
||||
"https://adguardteam.github.io/HostlistsRegistry/assets/filter_18.txt",
|
||||
"https://adguardteam.github.io/HostlistsRegistry/assets/filter_23.txt",
|
||||
"https://adguardteam.github.io/HostlistsRegistry/assets/filter_11.txt",
|
||||
"https://adguardteam.github.io/HostlistsRegistry/assets/filter_9.txt",
|
||||
"https://adguardteam.github.io/HostlistsRegistry/assets/filter_50.txt",
|
||||
"https://raw.githubusercontent.com/DandelionSprout/adfilt/master/Alternate%20versions%20Anti-Malware%20List/AntiMalwareHosts.txt",
|
||||
"https://osint.digitalside.it/Threat-Intel/lists/latestdomains.txt",
|
||||
"https://v.firebog.net/hosts/Prigent-Crypto.txt",
|
||||
"https://phishing.army/download/phishing_army_blocklist_extended.txt",
|
||||
"https://v.firebog.net/hosts/static/w3kbl.txt",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func loadConfig() {
|
||||
configMu.Lock()
|
||||
defer configMu.Unlock()
|
||||
|
||||
file, err := os.Open(configFile)
|
||||
if err != nil {
|
||||
log.Println("Config not found, creating default")
|
||||
// Create default config with admin user
|
||||
defaultConfig := getDefaultConfig()
|
||||
hashed, _ := bcrypt.GenerateFromPassword([]byte("Password123!"), bcrypt.DefaultCost)
|
||||
defaultConfig.HashedPass = string(hashed)
|
||||
config = defaultConfig
|
||||
saveConfigLocked()
|
||||
log.Println("Default config created with admin/Password123!")
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
err = json.NewDecoder(file).Decode(&config)
|
||||
if err != nil {
|
||||
log.Printf("Error reading config: %v, using defaults", err)
|
||||
defaultConfig := getDefaultConfig()
|
||||
hashed, _ := bcrypt.GenerateFromPassword([]byte("Password123!"), bcrypt.DefaultCost)
|
||||
defaultConfig.HashedPass = string(hashed)
|
||||
config = defaultConfig
|
||||
}
|
||||
}
|
||||
|
||||
func saveConfigLocked() {
|
||||
file, err := os.Create(configFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
encoder := json.NewEncoder(file)
|
||||
encoder.SetIndent("", " ")
|
||||
err = encoder.Encode(config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func saveConfig() {
|
||||
configMu.Lock()
|
||||
defer configMu.Unlock()
|
||||
|
||||
saveConfigLocked()
|
||||
}
|
||||
|
||||
func handleMFACommand(cmd string) {
|
||||
switch cmd {
|
||||
case "on":
|
||||
configMu.Lock()
|
||||
if config.MFASecret == "" {
|
||||
// Generate new secret
|
||||
key, err := totp.Generate(totp.GenerateOpts{
|
||||
Issuer: "UnifiBlocklist",
|
||||
AccountName: config.Username,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error generating MFA: %v\n", err)
|
||||
configMu.Unlock()
|
||||
os.Exit(1)
|
||||
}
|
||||
config.MFASecret = key.Secret()
|
||||
saveConfigLocked()
|
||||
fmt.Printf("MFA enabled.\nSecret: %s\nOTP URL: %s\n", key.Secret(), key.URL())
|
||||
} else {
|
||||
fmt.Println("MFA is already enabled")
|
||||
configMu.Unlock()
|
||||
return
|
||||
}
|
||||
configMu.Unlock()
|
||||
|
||||
case "off":
|
||||
configMu.Lock()
|
||||
if config.MFASecret != "" {
|
||||
config.MFASecret = ""
|
||||
saveConfigLocked()
|
||||
fmt.Println("MFA disabled")
|
||||
} else {
|
||||
fmt.Println("MFA is not enabled")
|
||||
}
|
||||
configMu.Unlock()
|
||||
|
||||
case "reset":
|
||||
configMu.Lock()
|
||||
key, err := totp.Generate(totp.GenerateOpts{
|
||||
Issuer: "UnifiBlocklist",
|
||||
AccountName: config.Username,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error generating MFA: %v\n", err)
|
||||
configMu.Unlock()
|
||||
os.Exit(1)
|
||||
}
|
||||
config.MFASecret = key.Secret()
|
||||
saveConfigLocked()
|
||||
fmt.Printf("MFA reset.\nNew Secret: %s\nOTP URL: %s\nScan with your authenticator app.\n", key.Secret(), key.URL())
|
||||
configMu.Unlock()
|
||||
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "Invalid MFA command. Use: on, off, or reset\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user