mirror of
https://github.com/shlldev/miniws.git
synced 2025-09-02 19:00:59 +02:00
Merge branch 'master' of https://github.com/shlldev/miniws
This commit is contained in:
141
main.go
141
main.go
@@ -1,10 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -15,37 +17,63 @@ import (
|
||||
const (
|
||||
PATH_ACCESSLOG string = "access.log"
|
||||
PATH_ERRORLOG string = "error.log"
|
||||
PATH_IPFILTER string = "ipfilter.conf"
|
||||
PATH_USERAGENTFILTER string = "useragentfilter.conf"
|
||||
FLAGS_LOG_OPEN int = os.O_APPEND | os.O_WRONLY | os.O_CREATE
|
||||
FLAGS_CONFIG_OPEN int = os.O_RDONLY | os.O_CREATE
|
||||
PERMS_LOG_OPEN os.FileMode = os.ModeType | os.ModePerm
|
||||
PERMS_CONFIG_OPEN os.FileMode = os.ModeType | os.ModePerm
|
||||
PERMS_MKDIR os.FileMode = os.ModeDir | os.ModePerm
|
||||
FILTER_MODE_WHITELIST = 0
|
||||
FILTER_MODE_BLACKLIST = 1
|
||||
)
|
||||
|
||||
var _logFolder string = ""
|
||||
var (
|
||||
logFolder string = ""
|
||||
configFolder string = ""
|
||||
ipFilter []string = make([]string, 0)
|
||||
ipFilterMode = FILTER_MODE_WHITELIST
|
||||
userAgentFilter []string = make([]string, 0)
|
||||
userAgentFilterMode = FILTER_MODE_WHITELIST
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
parser := argparse.NewParser("miniws", "")
|
||||
port := parser.String("p", "port", &argparse.Options{Default: "8040"})
|
||||
logFolder := parser.String("l", "logs-folder", &argparse.Options{Default: "logs"})
|
||||
_logFolder := parser.String("l", "logs-folder", &argparse.Options{Default: "logs"})
|
||||
_configFolder := parser.String("c", "config-folder", &argparse.Options{Default: "config"})
|
||||
|
||||
err := parser.Parse(os.Args)
|
||||
if err != nil {
|
||||
// In case of error print error and print usage
|
||||
// This can also be done by passing -h or --help flags
|
||||
fmt.Print(parser.Usage(err))
|
||||
return
|
||||
}
|
||||
|
||||
_logFolder = *logFolder
|
||||
logFolder = *_logFolder
|
||||
configFolder = *_configFolder
|
||||
|
||||
http.HandleFunc("/{resource...}", get)
|
||||
parseIpFilter()
|
||||
parseUserAgentFilter()
|
||||
http.HandleFunc("/", get)
|
||||
log.Println("Server started on port " + *port)
|
||||
http.ListenAndServe(":"+*port, nil)
|
||||
}
|
||||
|
||||
func get(writer http.ResponseWriter, req *http.Request) {
|
||||
|
||||
respStatusCode := http.StatusOK
|
||||
|
||||
if !isIpValid(req.RemoteAddr) || !isUserAgentValid(req.UserAgent()) {
|
||||
writer.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
fetchedData, fetchErr := fetchFileContents(req.URL.Path)
|
||||
|
||||
sentBytes := 0
|
||||
respStatusCode := http.StatusOK
|
||||
|
||||
if logIfError(fetchErr) {
|
||||
respStatusCode = http.StatusNotFound
|
||||
@@ -102,22 +130,22 @@ func logAccess(
|
||||
out := fmt.Sprintf("%v %v %v [%v] \"%v\" %v %v \"%v\" \"%v\"\n",
|
||||
remoteAddr, identifier, authuser, timestamp, request, status, bytesSent, referer, user_agent,
|
||||
)
|
||||
os.Mkdir(_logFolder, os.ModeDir|os.ModePerm)
|
||||
file, err := os.OpenFile(ensureSlashSuffix(_logFolder)+PATH_ACCESSLOG, FLAGS_LOG_OPEN, PERMS_LOG_OPEN)
|
||||
os.Mkdir(logFolder, os.ModeDir|os.ModePerm)
|
||||
file, err := os.OpenFile(ensureSlashSuffix(logFolder)+PATH_ACCESSLOG, FLAGS_LOG_OPEN, PERMS_LOG_OPEN)
|
||||
|
||||
if err != nil {
|
||||
log.Println("couldn't open log access file at", ensureSlashSuffix(_logFolder)+PATH_ACCESSLOG)
|
||||
log.Println("couldn't open log access file at", ensureSlashSuffix(logFolder)+PATH_ACCESSLOG)
|
||||
}
|
||||
defer file.Close()
|
||||
file.WriteString(out)
|
||||
}
|
||||
|
||||
func logError(str string) {
|
||||
os.Mkdir(_logFolder, os.ModeDir|os.ModePerm)
|
||||
file, err := os.OpenFile(ensureSlashSuffix(_logFolder)+PATH_ERRORLOG, FLAGS_LOG_OPEN, PERMS_LOG_OPEN)
|
||||
os.Mkdir(logFolder, PERMS_MKDIR)
|
||||
file, err := os.OpenFile(ensureSlashSuffix(logFolder)+PATH_ERRORLOG, FLAGS_LOG_OPEN, PERMS_LOG_OPEN)
|
||||
|
||||
if err != nil {
|
||||
log.Println("couldn't open log error file at", ensureSlashSuffix(_logFolder)+PATH_ERRORLOG)
|
||||
log.Println("couldn't open log error file at", ensureSlashSuffix(logFolder)+PATH_ERRORLOG)
|
||||
}
|
||||
defer file.Close()
|
||||
file.WriteString(str + "\n")
|
||||
@@ -137,3 +165,94 @@ func getOrDash(str string) string {
|
||||
func ensureSlashSuffix(str string) string {
|
||||
return strings.TrimSuffix(str, "/") + "/"
|
||||
}
|
||||
|
||||
func isIpValid(ip string) bool {
|
||||
ip = strings.Split(ip, ":")[0] // remove port
|
||||
switch ipFilterMode {
|
||||
case FILTER_MODE_WHITELIST:
|
||||
return slices.Contains(ipFilter, ip)
|
||||
case FILTER_MODE_BLACKLIST:
|
||||
return !slices.Contains(ipFilter, ip)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func isUserAgentValid(userAgent string) bool {
|
||||
switch userAgentFilterMode {
|
||||
case FILTER_MODE_WHITELIST:
|
||||
return slices.Contains(userAgentFilter, userAgent)
|
||||
case FILTER_MODE_BLACKLIST:
|
||||
return !slices.Contains(userAgentFilter, userAgent)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func parseIpFilter() {
|
||||
os.Mkdir(configFolder, PERMS_MKDIR)
|
||||
fileinfo, err := os.Stat(ensureSlashSuffix(configFolder) + PATH_IPFILTER)
|
||||
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
os.Create(ensureSlashSuffix(configFolder) + PATH_IPFILTER)
|
||||
}
|
||||
if fileinfo.Size() == 0 { // empty config
|
||||
ipFilterMode = FILTER_MODE_BLACKLIST
|
||||
ipFilter = make([]string, 0)
|
||||
return
|
||||
}
|
||||
ipFilterContent, err := os.ReadFile(ensureSlashSuffix(configFolder) + PATH_IPFILTER)
|
||||
|
||||
if logIfError(err) {
|
||||
return
|
||||
}
|
||||
|
||||
ipFilterLines := strings.Split(string(ipFilterContent), "\n")
|
||||
|
||||
_ipFilterMode := ipFilterLines[0]
|
||||
|
||||
switch _ipFilterMode {
|
||||
case "allow":
|
||||
ipFilterMode = FILTER_MODE_WHITELIST
|
||||
case "deny":
|
||||
ipFilterMode = FILTER_MODE_BLACKLIST
|
||||
default:
|
||||
logError("invalid ip filter mode, use allow|deny")
|
||||
}
|
||||
|
||||
ipFilter = ipFilterLines[1:]
|
||||
|
||||
}
|
||||
|
||||
func parseUserAgentFilter() {
|
||||
os.Mkdir(configFolder, PERMS_MKDIR)
|
||||
fileinfo, err := os.Stat(ensureSlashSuffix(configFolder) + PATH_USERAGENTFILTER)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
os.Create(ensureSlashSuffix(configFolder) + PATH_USERAGENTFILTER)
|
||||
}
|
||||
if fileinfo.Size() == 0 { // empty config
|
||||
userAgentFilterMode = FILTER_MODE_BLACKLIST
|
||||
userAgentFilter = make([]string, 0)
|
||||
return
|
||||
}
|
||||
|
||||
userAgentFilterContent, err := os.ReadFile(ensureSlashSuffix(configFolder) + PATH_USERAGENTFILTER)
|
||||
|
||||
if logIfError(err) {
|
||||
return
|
||||
}
|
||||
|
||||
userAgentFilterLines := strings.Split(string(userAgentFilterContent), "\n")
|
||||
_userAgentFilterMode := userAgentFilterLines[0]
|
||||
|
||||
println(len(userAgentFilterLines))
|
||||
switch _userAgentFilterMode {
|
||||
case "allow":
|
||||
userAgentFilterMode = FILTER_MODE_WHITELIST
|
||||
case "deny":
|
||||
userAgentFilterMode = FILTER_MODE_BLACKLIST
|
||||
default:
|
||||
logError("invalid userAgent filter mode, use allow|deny")
|
||||
}
|
||||
userAgentFilter = userAgentFilterLines[1:]
|
||||
}
|
||||
|
Reference in New Issue
Block a user