summaryrefslogtreecommitdiff
path: root/internal/config/modes.go
diff options
context:
space:
mode:
authorSergeiEU <39683682+SergeiEU@users.noreply.github.com>2026-04-01 10:17:15 +0400
committerSergeiEU <39683682+SergeiEU@users.noreply.github.com>2026-04-01 10:17:15 +0400
commit1bd203c5555046b7ee4fbfe2f822eb3d03571ad7 (patch)
treed8c85273ede547e03a5727bf185f5d07e87b4a08 /internal/config/modes.go
downloadvpnem-1bd203c5555046b7ee4fbfe2f822eb3d03571ad7.tar.gz
vpnem-1bd203c5555046b7ee4fbfe2f822eb3d03571ad7.tar.bz2
vpnem-1bd203c5555046b7ee4fbfe2f822eb3d03571ad7.zip
Initial importHEADmain
Diffstat (limited to 'internal/config/modes.go')
-rw-r--r--internal/config/modes.go176
1 files changed, 176 insertions, 0 deletions
diff --git a/internal/config/modes.go b/internal/config/modes.go
new file mode 100644
index 0000000..22f1d2e
--- /dev/null
+++ b/internal/config/modes.go
@@ -0,0 +1,176 @@
+package config
+
+// Mode defines a routing mode with its specific rules.
+type Mode struct {
+ Name string
+ Final string // "direct" or "proxy"
+ Rules []Rule
+}
+
+// Rule represents a single sing-box routing rule.
+type Rule struct {
+ DomainSuffix []string `json:"domain_suffix,omitempty"`
+ DomainRegex []string `json:"domain_regex,omitempty"`
+ IPCIDR []string `json:"ip_cidr,omitempty"`
+ RuleSet []string `json:"rule_set,omitempty"`
+ Network []string `json:"network,omitempty"`
+ PortRange []string `json:"port_range,omitempty"`
+ Outbound string `json:"outbound"`
+}
+
+// Discord IPs — ported 1:1 from vpn.py.
+var DiscordIPs = []string{
+ "162.159.130.234/32", "162.159.134.234/32", "162.159.133.234/32",
+ "162.159.135.234/32", "162.159.136.234/32", "162.159.137.232/32",
+ "162.159.135.232/32", "162.159.136.232/32", "162.159.138.232/32",
+ "162.159.128.233/32", "198.244.231.90/32", "162.159.129.233/32",
+ "162.159.130.233/32", "162.159.133.233/32", "162.159.134.233/32",
+ "162.159.135.233/32", "162.159.138.234/32", "162.159.137.234/32",
+ "162.159.134.232/32", "162.159.130.235/32", "162.159.129.235/32",
+ "162.159.129.232/32", "162.159.128.235/32", "162.159.130.232/32",
+ "162.159.133.232/32", "162.159.128.232/32", "34.126.226.51/32",
+ // Voice
+ "66.22.243.0/24", "64.233.165.94/32", "35.207.188.57/32",
+ "35.207.81.249/32", "35.207.171.222/32", "195.62.89.0/24",
+ "66.22.192.0/18", "66.22.196.0/24", "66.22.197.0/24",
+ "66.22.198.0/24", "66.22.199.0/24", "66.22.216.0/24",
+ "66.22.217.0/24", "66.22.237.0/24", "66.22.238.0/24",
+ "66.22.241.0/24", "66.22.242.0/24", "66.22.244.0/24",
+ "64.71.8.96/29", "34.0.240.0/24", "34.0.241.0/24",
+ "34.0.242.0/24", "34.0.243.0/24", "34.0.244.0/24",
+ "34.0.245.0/24", "34.0.246.0/24", "34.0.247.0/24",
+ "34.0.248.0/24", "34.0.249.0/24", "34.0.250.0/24",
+ "34.0.251.0/24", "12.129.184.160/29", "138.128.136.0/21",
+ "162.158.0.0/15", "172.64.0.0/13", "34.0.0.0/15",
+ "34.2.0.0/15", "35.192.0.0/12", "35.208.0.0/12",
+ "5.200.14.128/25",
+}
+
+var DiscordDomains = []string{
+ "discord.com", "discord.gg", "discordapp.com",
+ "discord.media", "discordapp.net", "discord.net",
+}
+
+var DiscordDomainRegex = []string{".*discord.*"}
+
+var TeamsDomains = []string{
+ "teams.microsoft.com", "teams.cloud.microsoft", "lync.com",
+ "skype.com", "keydelivery.mediaservices.windows.net",
+ "streaming.mediaservices.windows.net",
+}
+
+var TeamsIPs = []string{
+ "52.112.0.0/14", "52.122.0.0/15",
+}
+
+var TeamsDomainRegex = []string{
+ `.*teams\.microsoft.*`, ".*lync.*", ".*skype.*",
+}
+
+var LovenseDomains = []string{
+ "lovense-api.com", "lovense.com", "lovense.club",
+}
+
+var LovenseDomainRegex = []string{".*lovense.*"}
+
+var OBSDomains = []string{"obsproject.com"}
+var OBSDomainRegex = []string{".*obsproject.*"}
+
+var AnyDeskDomains = []string{
+ "anydesk.com", "anydesk.com.cn", "net.anydesk.com",
+}
+
+var AnyDeskDomainRegex = []string{".*anydesk.*"}
+
+// AllModes returns all available routing modes.
+func AllModes() []Mode {
+ baseDomains := append(append(append(
+ LovenseDomains, OBSDomains...), AnyDeskDomains...), IPCheckDomains...)
+ baseRegex := append(append(
+ LovenseDomainRegex, OBSDomainRegex...), AnyDeskDomainRegex...)
+
+ discordDomains := append(append([]string{}, baseDomains...), DiscordDomains...)
+ discordRegex := append(append([]string{}, baseRegex...), DiscordDomainRegex...)
+
+ teamsDomains := append(append([]string{}, discordDomains...), TeamsDomains...)
+ teamsRegex := append(append([]string{}, discordRegex...), TeamsDomainRegex...)
+
+ return []Mode{
+ {
+ Name: "Lovense + OBS + AnyDesk",
+ Final: "direct",
+ Rules: []Rule{
+ {DomainSuffix: baseDomains, DomainRegex: baseRegex, Outbound: "proxy"},
+ },
+ },
+ {
+ Name: "Lovense + OBS + AnyDesk + Discord",
+ Final: "direct",
+ Rules: []Rule{
+ {DomainSuffix: discordDomains, DomainRegex: discordRegex, Outbound: "proxy"},
+ {IPCIDR: DiscordIPs, Outbound: "proxy"},
+ {Network: []string{"udp"}, PortRange: []string{"50000:65535"}, Outbound: "proxy"},
+ },
+ },
+ {
+ Name: "Lovense + OBS + AnyDesk + Discord + Teams",
+ Final: "direct",
+ Rules: []Rule{
+ {DomainSuffix: teamsDomains, DomainRegex: teamsRegex, Outbound: "proxy"},
+ {IPCIDR: append(append([]string{}, DiscordIPs...), TeamsIPs...), Outbound: "proxy"},
+ {Network: []string{"udp"}, PortRange: []string{"3478:3481", "50000:65535"}, Outbound: "proxy"},
+ },
+ },
+ {
+ Name: "Discord Only",
+ Final: "direct",
+ Rules: []Rule{
+ {DomainSuffix: append(append([]string{}, DiscordDomains...), IPCheckDomains...), DomainRegex: DiscordDomainRegex, Outbound: "proxy"},
+ {IPCIDR: DiscordIPs, Outbound: "proxy"},
+ {Network: []string{"udp"}, PortRange: []string{"50000:65535"}, Outbound: "proxy"},
+ },
+ },
+ {
+ Name: "Full (All Traffic)",
+ Final: "proxy",
+ Rules: nil,
+ },
+ {
+ Name: "Re-filter (обход блокировок РФ)",
+ Final: "direct",
+ Rules: []Rule{
+ {RuleSet: []string{"refilter-domains", "refilter-ip", "discord-voice"}, Outbound: "proxy"},
+ },
+ },
+ {
+ Name: "Комбо (приложения + Re-filter)",
+ Final: "direct",
+ Rules: []Rule{
+ {DomainSuffix: discordDomains, DomainRegex: discordRegex, Outbound: "proxy"},
+ {IPCIDR: DiscordIPs, Outbound: "proxy"},
+ {Network: []string{"udp"}, PortRange: []string{"50000:65535"}, Outbound: "proxy"},
+ {RuleSet: []string{"refilter-domains", "refilter-ip", "discord-voice"}, Outbound: "proxy"},
+ },
+ },
+ }
+}
+
+// ModeByName finds a mode by name, returns nil if not found.
+func ModeByName(name string) *Mode {
+ for _, m := range AllModes() {
+ if m.Name == name {
+ return &m
+ }
+ }
+ return nil
+}
+
+// ModeNames returns all available mode names.
+func ModeNames() []string {
+ modes := AllModes()
+ names := make([]string, len(modes))
+ for i, m := range modes {
+ names[i] = m.Name
+ }
+ return names
+}