mirror of
https://github.com/SunBK201/UA3F.git
synced 2025-12-16 08:44:29 +00:00
feat: port user group management
This commit is contained in:
parent
bdd13b0b86
commit
a7a9f45145
@ -6,71 +6,6 @@ START=99
|
||||
|
||||
NAME="ua3f"
|
||||
PROG="/usr/bin/$NAME"
|
||||
SERVER_MODE=""
|
||||
UA3F_GROUP="nogroup"
|
||||
LOG_FILE="/var/log/ua3f/ua3f.log"
|
||||
|
||||
LOG() {
|
||||
if [ -n "${1}" ]; then
|
||||
printf '[%s] %s\n' "$(date "+%Y-%m-%d %H:%M:%S")" "$1" >>"$LOG_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
opkg_available() { command -v opkg >/dev/null 2>&1; }
|
||||
|
||||
openclash_exists() {
|
||||
if opkg_available; then
|
||||
if opkg list-installed luci-app-openclash | grep -q 'luci-app-openclash'; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
openclash_running() {
|
||||
if pgrep -f "openclash" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
shellclash_exists() {
|
||||
if id -u shellclash >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
if id -u shellcrash >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
shellclash_running() {
|
||||
if pgrep -f "ShellCrash" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
set_ua3f_group() {
|
||||
if [ "$SERVER_MODE" = "REDIRECT" ]; then
|
||||
UA3F_GROUP="root"
|
||||
return
|
||||
elif [ "$SERVER_MODE" = "NFQUEUE" ]; then
|
||||
UA3F_GROUP="root"
|
||||
return
|
||||
fi
|
||||
if openclash_running; then
|
||||
UA3F_GROUP="nogroup"
|
||||
elif shellclash_running; then
|
||||
UA3F_GROUP="shellcrash"
|
||||
elif openclash_exists; then
|
||||
UA3F_GROUP="nogroup"
|
||||
elif shellclash_exists; then
|
||||
UA3F_GROUP="shellcrash"
|
||||
else
|
||||
UA3F_GROUP="nogroup"
|
||||
fi
|
||||
}
|
||||
|
||||
start_service() {
|
||||
config_load "$NAME"
|
||||
@ -83,10 +18,10 @@ start_service() {
|
||||
config_get_bool enabled "enabled" "enabled" "0"
|
||||
[ "$enabled" -eq "1" ] || return 0
|
||||
|
||||
local port bind ua log_level ua_regex partial_replace
|
||||
local server_mode port bind ua log_level ua_regex partial_replace
|
||||
local rewrite_mode rewrite_rules
|
||||
local set_ttl set_ipid del_tcpts
|
||||
config_get SERVER_MODE "main" "server_mode" "TPROXY"
|
||||
config_get server_mode "main" "server_mode" "TPROXY"
|
||||
config_get port "main" "port" "1080"
|
||||
config_get bind "main" "bind" "127.0.0.1"
|
||||
config_get ua "main" "ua" "FFF"
|
||||
@ -99,21 +34,16 @@ start_service() {
|
||||
config_get_bool set_ipid "main" "set_ipid" 0
|
||||
config_get_bool del_tcpts "main" "del_tcpts" 0
|
||||
|
||||
# compose set_ttl set_ipid del_tcpts with others ",ttl,ipid,tcpts,"
|
||||
local others=","
|
||||
[ "$set_ipid" -eq "1" ] && others="${others}ipid,"
|
||||
[ "$del_tcpts" -eq "1" ] && others="${others}tcpts,"
|
||||
[ "$set_ttl" -eq "1" ] && others="${others}ttl,"
|
||||
|
||||
SERVER_MODE="$(echo "$SERVER_MODE" | tr '[:lower:]' '[:upper:]')"
|
||||
|
||||
set_ua3f_group
|
||||
LOG "Server Mode: $SERVER_MODE"
|
||||
LOG "Group: $UA3F_GROUP"
|
||||
|
||||
procd_open_instance "$NAME"
|
||||
procd_set_param command "$PROG"
|
||||
procd_append_param command -m "$SERVER_MODE"
|
||||
procd_append_param command -m "$server_mode"
|
||||
procd_append_param command -p "$port"
|
||||
procd_append_param command -b "$bind"
|
||||
procd_append_param command -f "$ua"
|
||||
@ -128,11 +58,8 @@ start_service() {
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_set_param limits nproc="unlimited" as="unlimited" memlock="unlimited" nofile="65535 65535"
|
||||
procd_set_param group $UA3F_GROUP
|
||||
|
||||
procd_close_instance
|
||||
|
||||
LOG "$NAME service started"
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
|
||||
11
src/internal/usergroup/usergroup_others.go
Normal file
11
src/internal/usergroup/usergroup_others.go
Normal file
@ -0,0 +1,11 @@
|
||||
//go:build !linux
|
||||
|
||||
package usergroup
|
||||
|
||||
import (
|
||||
"github.com/sunbk201/ua3f/internal/config"
|
||||
)
|
||||
|
||||
func SetUserGroup(cfg *config.Config) error {
|
||||
return nil
|
||||
}
|
||||
138
src/internal/usergroup/usergroup_unix.go
Normal file
138
src/internal/usergroup/usergroup_unix.go
Normal file
@ -0,0 +1,138 @@
|
||||
//go:build linux
|
||||
|
||||
package usergroup
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/sunbk201/ua3f/internal/config"
|
||||
)
|
||||
|
||||
func SetUserGroup(cfg *config.Config) error {
|
||||
groupName := determineGroup(cfg.ServerMode)
|
||||
if groupName == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
gid, err := getGroupID(groupName)
|
||||
if err != nil {
|
||||
slog.Warn("getGroupID", slog.String("group", groupName), slog.Any("error", err))
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := syscall.Setgid(gid); err != nil {
|
||||
if err == syscall.EPERM {
|
||||
slog.Warn("syscall.Setgid", slog.String("group", groupName), slog.Int("gid", gid), slog.Any("error", err))
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("syscall.Setgid: %w", err)
|
||||
}
|
||||
|
||||
slog.Info("Setup user group", slog.String("group", groupName), slog.Int("gid", gid))
|
||||
return nil
|
||||
}
|
||||
|
||||
func determineGroup(serverMode config.ServerMode) string {
|
||||
if serverMode == config.ServerModeRedirect || serverMode == config.ServerModeNFQueue {
|
||||
return "root"
|
||||
}
|
||||
|
||||
if processRunning("openclash") {
|
||||
return "nogroup"
|
||||
}
|
||||
|
||||
if processRunning("ShellCrash") {
|
||||
return "shellcrash"
|
||||
}
|
||||
|
||||
if openClashExists() {
|
||||
return "nogroup"
|
||||
}
|
||||
|
||||
if shellClashExists() {
|
||||
return "shellcrash"
|
||||
}
|
||||
|
||||
return "nogroup"
|
||||
}
|
||||
|
||||
func openClashExists() bool {
|
||||
if !opkgAvailable() {
|
||||
return false
|
||||
}
|
||||
|
||||
cmd := exec.Command("opkg", "list-installed", "luci-app-openclash")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return strings.Contains(string(output), "luci-app-openclash")
|
||||
}
|
||||
|
||||
func shellClashExists() bool {
|
||||
if userExists("shellclash") {
|
||||
return true
|
||||
}
|
||||
if userExists("shellcrash") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func opkgAvailable() bool {
|
||||
_, err := exec.LookPath("opkg")
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func processRunning(name string) bool {
|
||||
cmd := exec.Command("pgrep", "-f", name)
|
||||
err := cmd.Run()
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func userExists(username string) bool {
|
||||
cmd := exec.Command("id", "-u", username)
|
||||
err := cmd.Run()
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func getGroupID(groupName string) (int, error) {
|
||||
if groupName == "root" {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
file, err := os.Open("/etc/group")
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to open /etc/group: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = file.Close()
|
||||
}()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
parts := strings.Split(line, ":")
|
||||
if len(parts) >= 3 && parts[0] == groupName {
|
||||
gid, err := strconv.Atoi(parts[2])
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to parse GID for group %s: %w", groupName, err)
|
||||
}
|
||||
return gid, nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return 0, fmt.Errorf("error reading /etc/group: %w", err)
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("group %s not found", groupName)
|
||||
}
|
||||
@ -14,6 +14,7 @@ import (
|
||||
"github.com/sunbk201/ua3f/internal/server"
|
||||
"github.com/sunbk201/ua3f/internal/server/netlink"
|
||||
"github.com/sunbk201/ua3f/internal/statistics"
|
||||
"github.com/sunbk201/ua3f/internal/usergroup"
|
||||
)
|
||||
|
||||
var appVersion = "Development"
|
||||
@ -30,6 +31,11 @@ func main() {
|
||||
|
||||
log.LogHeader(appVersion, cfg)
|
||||
|
||||
if err := usergroup.SetUserGroup(cfg); err != nil {
|
||||
slog.Error("usergroup.SetUserGroup", slog.Any("error", err))
|
||||
return
|
||||
}
|
||||
|
||||
rw, err := rewrite.New(cfg)
|
||||
if err != nil {
|
||||
slog.Error("rewrite.New", slog.Any("error", err))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user