From eb6d089b1a3aaf3e885c14bdaf94e60dfa423220 Mon Sep 17 00:00:00 2001 From: Mehdikhody Date: Sat, 10 Feb 2024 05:21:40 +0330 Subject: [PATCH] Add ClientIPListener to handle client IP addresses --- xray/client_ip.go | 115 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 xray/client_ip.go diff --git a/xray/client_ip.go b/xray/client_ip.go new file mode 100644 index 00000000..cfe18082 --- /dev/null +++ b/xray/client_ip.go @@ -0,0 +1,115 @@ +package xray + +import ( + "errors" + "os/exec" + "regexp" + "strings" + "x-ui/logger" +) + +var customChain string = "IPLIMIT" +var listener *ClientIPListener + +type ClientIPListener struct { + p *process + logWriter *LogWriter + InboundClientIps map[string][]string + blacklist []string +} + +func NewClientIPListener(p *process) *ClientIPListener { + listener = &ClientIPListener{ + p: p, + logWriter: p.logWriter, + InboundClientIps: make(map[string][]string), + blacklist: make([]string, 0), + } + + return listener +} + +func GetClientIPListener() (*ClientIPListener, error) { + if listener == nil { + return nil, errors.New("ClientIPListener is not initialized") + } + + return listener, nil +} + +func (l *ClientIPListener) GetOnlineClients() []string { + return listener.p.onlineClients +} + +func (l *ClientIPListener) processLine(line string) { + ipRegx, _ := regexp.Compile(`((\d+\.\d+\.\d+\.\d+)|(\[.*\])).* accepted`) + emailRegx, _ := regexp.Compile(`email:.+`) + + matches := ipRegx.FindStringSubmatch(line) + if len(matches) > 1 { + ip := matches[1] + if ip == "127.0.0.1" || ip == "[::1]" { + logger.Debug("Skip localhost IP: ", ip) + return + } + + matchesEmail := emailRegx.FindString(line) + if matchesEmail == "" { + return + } + + matchesEmail = strings.TrimSpace(strings.Split(matchesEmail, "email: ")[1]) + if l.InboundClientIps[matchesEmail] != nil { + if l.contains(l.InboundClientIps[matchesEmail], ip) { + return + } + l.InboundClientIps[matchesEmail] = append(l.InboundClientIps[matchesEmail], ip) + } else { + l.InboundClientIps[matchesEmail] = append(l.InboundClientIps[matchesEmail], ip) + } + + logger.Info("Client IP: ", ip, " Email: ", matchesEmail) + } +} + +func (l *ClientIPListener) ProcessBlacklist() { + unbanCmd := exec.Command("iptables", "-F", customChain) + _ = unbanCmd.Run() + + for _, ip := range l.blacklist { + banCmd := exec.Command("iptables", "-A", customChain, "-s", ip, "-j", "DROP") + _ = banCmd.Run() + } +} + +func (l *ClientIPListener) contains(s []string, str string) bool { + for _, v := range s { + if v == str { + return true + } + } + + return false +} + +// Start listening to the xray stdout +func (l *ClientIPListener) Start() { + l.logWriter.SetListener(l.processLine) +} + +func (l *ClientIPListener) UnbanAllIPs() { + l.blacklist = make([]string, 0) +} + +func (l *ClientIPListener) UnbanIP(ip string) { + for i, v := range l.blacklist { + if v == ip { + l.blacklist = append(l.blacklist[:i], l.blacklist[i+1:]...) + return + } + } +} + +func (l *ClientIPListener) BanIP(ip string) { + l.blacklist = append(l.blacklist, ip) +}