mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-06 21:24:10 +00:00
fix
This commit is contained in:
parent
44ec6cf04c
commit
1bafa1fc37
2 changed files with 44 additions and 50 deletions
|
|
@ -6,6 +6,7 @@ package iptables
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -48,10 +49,23 @@ func FlushChain() error {
|
|||
|
||||
// BlockIP inserts a DROP rule for the given source IP on the given TCP destination
|
||||
// port into the custom chain. The comment embeds the current Unix timestamp so
|
||||
// the rule can be age-checked later.
|
||||
// the rule can be age-checked later. Duplicate rules are skipped.
|
||||
func BlockIP(ip string, port int) error {
|
||||
if net.ParseIP(ip) == nil {
|
||||
return fmt.Errorf("invalid IP address: %s", ip)
|
||||
}
|
||||
|
||||
// Skip if an identical rule already exists
|
||||
_, err := run("iptables", "-C", chain,
|
||||
"-s", ip,
|
||||
"-p", "tcp", "--dport", strconv.Itoa(port),
|
||||
"-j", "DROP")
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
comment := fmt.Sprintf("3xui:block:%d", time.Now().Unix())
|
||||
_, err := run("iptables", "-I", chain,
|
||||
_, err = run("iptables", "-I", chain,
|
||||
"-s", ip,
|
||||
"-p", "tcp", "--dport", strconv.Itoa(port),
|
||||
"-m", "comment", "--comment", comment,
|
||||
|
|
@ -64,6 +78,9 @@ func BlockIP(ip string, port int) error {
|
|||
|
||||
// UnblockIP removes the DROP rule for the given source IP and TCP destination port.
|
||||
func UnblockIP(ip string, port int) error {
|
||||
if net.ParseIP(ip) == nil {
|
||||
return fmt.Errorf("invalid IP address: %s", ip)
|
||||
}
|
||||
_, err := run("iptables", "-D", chain,
|
||||
"-s", ip,
|
||||
"-p", "tcp", "--dport", strconv.Itoa(port),
|
||||
|
|
@ -154,7 +171,7 @@ func findComment(ip string, port int) string {
|
|||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
needle := fmt.Sprintf("-s %s", ip)
|
||||
needle := fmt.Sprintf("-s %s/32", ip)
|
||||
dport := fmt.Sprintf("--dport %d", port)
|
||||
for _, line := range strings.Split(out, "\n") {
|
||||
if strings.Contains(line, needle) && strings.Contains(line, dport) {
|
||||
|
|
|
|||
|
|
@ -2532,19 +2532,16 @@ func (s *InboundService) DelInboundClientByEmail(inboundId int, email string) (b
|
|||
return needRestart, db.Save(oldInbound).Error
|
||||
}
|
||||
|
||||
// blockClientIPs inserts iptables DROP rules for all known IPs of the given client.
|
||||
// Failures are logged as warnings so a missing iptables binary does not break the
|
||||
// normal disable flow.
|
||||
func (s *InboundService) blockClientIPs(email string) {
|
||||
// clientIPsForFirewall returns the list of known IP addresses and the inbound port for a client.
|
||||
func (s *InboundService) clientIPsForFirewall(email string) ([]string, int) {
|
||||
ipsJSON, err := s.GetInboundClientIps(email)
|
||||
if err != nil || ipsJSON == "" {
|
||||
return
|
||||
return nil, 0
|
||||
}
|
||||
_, inbound, err := s.GetClientInboundByEmail(email)
|
||||
if err != nil || inbound == nil {
|
||||
return
|
||||
return nil, 0
|
||||
}
|
||||
port := inbound.Port
|
||||
|
||||
type IPWithTimestamp struct {
|
||||
IP string `json:"ip"`
|
||||
|
|
@ -2552,57 +2549,37 @@ func (s *InboundService) blockClientIPs(email string) {
|
|||
}
|
||||
var ipsWithTime []IPWithTimestamp
|
||||
if err := json.Unmarshal([]byte(ipsJSON), &ipsWithTime); err != nil {
|
||||
// Try simple string-array format
|
||||
var simpleIPs []string
|
||||
if err2 := json.Unmarshal([]byte(ipsJSON), &simpleIPs); err2 != nil {
|
||||
return
|
||||
return nil, 0
|
||||
}
|
||||
for _, ip := range simpleIPs {
|
||||
if berr := iptables.BlockIP(ip, port); berr != nil {
|
||||
logger.Warning("blockClientIPs: failed to block", ip, berr)
|
||||
}
|
||||
}
|
||||
return
|
||||
return simpleIPs, inbound.Port
|
||||
}
|
||||
ips := make([]string, 0, len(ipsWithTime))
|
||||
for _, entry := range ipsWithTime {
|
||||
if berr := iptables.BlockIP(entry.IP, port); berr != nil {
|
||||
logger.Warning("blockClientIPs: failed to block", entry.IP, berr)
|
||||
ips = append(ips, entry.IP)
|
||||
}
|
||||
return ips, inbound.Port
|
||||
}
|
||||
|
||||
// blockClientIPs inserts iptables DROP rules for all known IPs of the given client.
|
||||
// Failures are logged as warnings so a missing iptables binary does not break the
|
||||
// normal disable flow.
|
||||
func (s *InboundService) blockClientIPs(email string) {
|
||||
ips, port := s.clientIPsForFirewall(email)
|
||||
for _, ip := range ips {
|
||||
if err := iptables.BlockIP(ip, port); err != nil {
|
||||
logger.Warning("blockClientIPs: failed to block", ip, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unblockClientIPs removes iptables DROP rules for all known IPs of the given client.
|
||||
func (s *InboundService) unblockClientIPs(email string) {
|
||||
ipsJSON, err := s.GetInboundClientIps(email)
|
||||
if err != nil || ipsJSON == "" {
|
||||
return
|
||||
}
|
||||
_, inbound, err := s.GetClientInboundByEmail(email)
|
||||
if err != nil || inbound == nil {
|
||||
return
|
||||
}
|
||||
port := inbound.Port
|
||||
|
||||
type IPWithTimestamp struct {
|
||||
IP string `json:"ip"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
var ipsWithTime []IPWithTimestamp
|
||||
if err := json.Unmarshal([]byte(ipsJSON), &ipsWithTime); err != nil {
|
||||
var simpleIPs []string
|
||||
if err2 := json.Unmarshal([]byte(ipsJSON), &simpleIPs); err2 != nil {
|
||||
return
|
||||
}
|
||||
for _, ip := range simpleIPs {
|
||||
if uerr := iptables.UnblockIP(ip, port); uerr != nil {
|
||||
logger.Debug("unblockClientIPs: failed to unblock", ip, uerr)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
for _, entry := range ipsWithTime {
|
||||
if uerr := iptables.UnblockIP(entry.IP, port); uerr != nil {
|
||||
logger.Debug("unblockClientIPs: failed to unblock", entry.IP, uerr)
|
||||
ips, port := s.clientIPsForFirewall(email)
|
||||
for _, ip := range ips {
|
||||
if err := iptables.UnblockIP(ip, port); err != nil {
|
||||
logger.Debug("unblockClientIPs: failed to unblock", ip, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue