feat: Add LAN allowed and disallowed IP configurations (#861)

This commit is contained in:
Kuingsmile 2023-12-12 04:39:11 -08:00 committed by wwqgtxx
parent 3cf865e5f0
commit 7ee6809257
8 changed files with 103 additions and 3 deletions

View file

@ -0,0 +1,57 @@
package inbound
import (
"net"
"net/netip"
C "github.com/metacubex/mihomo/constant"
)
var lanAllowedIPs []netip.Prefix
var lanDisAllowedIPs []netip.Prefix
func SetAllowedIPs(prefixes []netip.Prefix) {
lanAllowedIPs = prefixes
}
func SetDisAllowedIPs(prefixes []netip.Prefix) {
lanDisAllowedIPs = prefixes
}
func AllowedIPs() []netip.Prefix {
return lanAllowedIPs
}
func DisAllowedIPs() []netip.Prefix {
return lanDisAllowedIPs
}
func IsRemoteAddrDisAllowed(addr net.Addr) bool {
m := C.Metadata{}
if err := m.SetRemoteAddr(addr); err != nil {
return false
}
return isAllowed(m.AddrPort().Addr().Unmap()) && !isDisAllowed(m.AddrPort().Addr().Unmap())
}
func isAllowed(addr netip.Addr) bool {
if addr.IsValid() {
for _, prefix := range lanAllowedIPs {
if prefix.Contains(addr) {
return true
}
}
}
return false
}
func isDisAllowed(addr netip.Addr) bool {
if addr.IsValid() {
for _, prefix := range lanDisAllowedIPs {
if prefix.Contains(addr) {
return true
}
}
}
return false
}

View file

@ -80,6 +80,8 @@ type Inbound struct {
VmessConfig string `json:"vmess-config"`
Authentication []string `json:"authentication"`
SkipAuthPrefixes []netip.Prefix `json:"skip-auth-prefixes"`
LanAllowedIPs []netip.Prefix `json:"lan-allowed-ips"`
LanDisAllowedIPs []netip.Prefix `json:"lan-disallowed-ips"`
AllowLan bool `json:"allow-lan"`
BindAddress string `json:"bind-address"`
InboundTfo bool `json:"inbound-tfo"`
@ -289,6 +291,8 @@ type RawConfig struct {
InboundMPTCP bool `yaml:"inbound-mptcp"`
Authentication []string `yaml:"authentication" json:"authentication"`
SkipAuthPrefixes []netip.Prefix `yaml:"skip-auth-prefixes"`
LanAllowedIPs []netip.Prefix `yaml:"lan-allowed-ips"`
LanDisAllowedIPs []netip.Prefix `yaml:"lan-disallowed-ips"`
AllowLan bool `yaml:"allow-lan" json:"allow-lan"`
BindAddress string `yaml:"bind-address" json:"bind-address"`
Mode T.TunnelMode `yaml:"mode" json:"mode"`
@ -387,6 +391,7 @@ func UnmarshalRawConfig(buf []byte) (*RawConfig, error) {
rawCfg := &RawConfig{
AllowLan: false,
BindAddress: "*",
LanAllowedIPs: []netip.Prefix{netip.MustParsePrefix("0.0.0.0/0"), netip.MustParsePrefix("::/0")},
IPv6: true,
Mode: T.Rule,
GeoAutoUpdate: false,
@ -647,6 +652,8 @@ func parseGeneral(cfg *RawConfig) (*General, error) {
VmessConfig: cfg.VmessConfig,
AllowLan: cfg.AllowLan,
SkipAuthPrefixes: cfg.SkipAuthPrefixes,
LanAllowedIPs: cfg.LanAllowedIPs,
LanDisAllowedIPs: cfg.LanDisAllowedIPs,
BindAddress: cfg.BindAddress,
InboundTfo: cfg.InboundTfo,
InboundMPTCP: cfg.InboundMPTCP,

View file

@ -13,6 +13,11 @@ authentication: # http,socks入口的验证用户名密码
skip-auth-prefixes: # 设置跳过验证的IP段
- 127.0.0.1/8
- ::1/128
lan-allowed-ips: # 允许连接的 IP 地址段,仅作用于 allow-lan 为 true, 默认值为0.0.0.0/0和::/0
- 0.0.0.0/0
- ::/0
lan-disallowed-ips: # 禁止连接的 IP 地址段, 黑名单优先级高于白名单, 默认值为空
- 192.168.0.3/32
# find-process-mode has 3 values:always, strict, off
# - always, 开启,强制匹配所有进程

View file

@ -141,6 +141,8 @@ func GetGeneral() *config.General {
VmessConfig: ports.VmessConfig,
Authentication: authenticator,
SkipAuthPrefixes: inbound.SkipAuthPrefixes(),
LanAllowedIPs: inbound.AllowedIPs(),
LanDisAllowedIPs: inbound.DisAllowedIPs(),
AllowLan: listener.AllowLan(),
BindAddress: listener.BindAddress(),
},
@ -166,6 +168,8 @@ func updateListeners(general *config.General, listeners map[string]C.InboundList
allowLan := general.AllowLan
listener.SetAllowLan(allowLan)
inbound.SetSkipAuthPrefixes(general.SkipAuthPrefixes)
inbound.SetAllowedIPs(general.LanAllowedIPs)
inbound.SetDisAllowedIPs(general.LanDisAllowedIPs)
bindAddress := general.BindAddress
listener.SetBindAddress(bindAddress)

View file

@ -10,7 +10,6 @@ import (
"github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/component/resolver"
"github.com/metacubex/mihomo/config"
"github.com/metacubex/mihomo/constant"
C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/hub/executor"
P "github.com/metacubex/mihomo/listener"
@ -50,6 +49,8 @@ type configSchema struct {
UdptunConfig *string `json:"udptun-config"`
AllowLan *bool `json:"allow-lan"`
SkipAuthPrefixes *[]netip.Prefix `json:"skip-auth-prefixes"`
LanAllowedIPs *[]netip.Prefix `json:"lan-allowed-ips"`
LanDisAllowedIPs *[]netip.Prefix `json:"lan-disallowed-ips"`
BindAddress *string `json:"bind-address"`
Mode *tunnel.TunnelMode `json:"mode"`
LogLevel *log.LogLevel `json:"log-level"`
@ -268,6 +269,14 @@ func patchConfigs(w http.ResponseWriter, r *http.Request) {
inbound.SetSkipAuthPrefixes(*general.SkipAuthPrefixes)
}
if general.LanAllowedIPs != nil {
inbound.SetAllowedIPs(*general.LanAllowedIPs)
}
if general.LanDisAllowedIPs != nil {
inbound.SetDisAllowedIPs(*general.LanDisAllowedIPs)
}
if general.BindAddress != nil {
P.SetBindAddress(*general.BindAddress)
}
@ -335,7 +344,7 @@ func updateConfigs(w http.ResponseWriter, r *http.Request) {
}
} else {
if req.Path == "" {
req.Path = constant.Path.Config()
req.Path = C.Path.Config()
}
if !filepath.IsAbs(req.Path) {
render.Status(r, http.StatusBadRequest)
@ -380,7 +389,7 @@ func updateGeoDatabases(w http.ResponseWriter, r *http.Request) {
return
}
cfg, err := executor.ParseWithPath(constant.Path.Config())
cfg, err := executor.ParseWithPath(C.Path.Config())
if err != nil {
log.Errorln("[REST-API] update GEO databases failed: %v", err)
return

View file

@ -71,6 +71,12 @@ func NewWithAuthenticate(addr string, tunnel C.Tunnel, authenticate bool, additi
t.SetKeepAlive(false)
}
}
if len(additions) == 0 { // only apply on default listener
if inbound.IsRemoteAddrDisAllowed(conn.RemoteAddr()) {
_ = conn.Close()
continue
}
}
go HandleConn(conn, tunnel, c, additions...)
}
}()

View file

@ -62,6 +62,12 @@ func New(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener
}
continue
}
if len(additions) == 0 { // only apply on default listener
if inbound.IsRemoteAddrDisAllowed(c.RemoteAddr()) {
_ = c.Close()
continue
}
}
go handleConn(c, tunnel, ml.cache, additions...)
}
}()

View file

@ -59,6 +59,12 @@ func New(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener
}
continue
}
if len(additions) == 0 { // only apply on default listener
if inbound.IsRemoteAddrDisAllowed(c.RemoteAddr()) {
_ = c.Close()
continue
}
}
go handleSocks(c, tunnel, additions...)
}
}()