diff --git a/conn/bind_linux.go b/conn/bind_linux.go index 0b7ae00..7ec783b 100644 --- a/conn/bind_linux.go +++ b/conn/bind_linux.go @@ -8,6 +8,7 @@ package conn import ( "errors" "net" + "net/netip" "strconv" "sync" "syscall" @@ -57,24 +58,45 @@ func (endpoint *LinuxSocketEndpoint) dst6() *unix.SockaddrInet6 { type LinuxSocketBind struct { // mu guards sock4 and sock6 and the associated fds. // As long as someone holds mu (read or write), the associated fds are valid. - mu sync.RWMutex - fwmark uint32 - sock4 int - sock6 int - use4 bool - use6 bool + mu sync.RWMutex + fwmark uint32 + sock4 int + sock6 int + use4 bool + use6 bool + listen_ip4 [4]byte + listen_ip6 [16]byte } func NewLinuxSocketBind() Bind { return &LinuxSocketBind{sock4: -1, sock6: -1, use4: true, use6: true} } -func NewLinuxSocketBindAf(use4 bool, use6 bool, fwmark uint32) Bind { - return &LinuxSocketBind{sock4: -1, sock6: -1, use4: use4, use6: use6, fwmark: fwmark} +func NewLinuxSocketBindAf(use4 bool, use6 bool, listen_ip4 [4]byte, listen_ip6 [16]byte, fwmark uint32) Bind { + return &LinuxSocketBind{sock4: -1, sock6: -1, use4: use4, use6: use6, fwmark: fwmark, listen_ip4: listen_ip4, listen_ip6: listen_ip6} } func NewDefaultBind(Af EnabledAf, bindmode string, fwmark uint32) Bind { - if bindmode == "std" { - return NewStdNetBindAf(Af.IPv4, Af.IPv6, fwmark) + listen_ip4 := Af.ListenIPv4 + listen_ip6 := Af.ListenIPv6 + var err error + ListenIP4, _ := netip.ParseAddr("0.0.0.0") + if listen_ip4 != "" { + ListenIP4, err = netip.ParseAddr(listen_ip4) + if err != nil { + ListenIP4, _ = netip.ParseAddr("0.0.0.0") + } } - return NewLinuxSocketBindAf(Af.IPv4, Af.IPv6, fwmark) + + ListenIP6, _ := netip.ParseAddr("::") + if listen_ip6 != "" { + ListenIP6, err = netip.ParseAddr(listen_ip6) + if err != nil { + ListenIP6, _ = netip.ParseAddr("::") + } + } + + if bindmode == "std" { + return NewStdNetBindAf(Af.IPv4, Af.IPv6, ListenIP4.As4(), ListenIP6.As16(), fwmark) + } + return NewLinuxSocketBindAf(Af.IPv4, Af.IPv6, ListenIP4.As4(), ListenIP6.As16(), fwmark) } var _ Endpoint = (*LinuxSocketEndpoint)(nil) @@ -82,8 +104,8 @@ var _ Bind = (*LinuxSocketBind)(nil) func (s *LinuxSocketBind) EnabledAf() EnabledAf { return EnabledAf{ - s.use4, - s.use6, + IPv4: s.use4, + IPv6: s.use6, } } @@ -141,7 +163,7 @@ again: var sock4, sock6 int if bind.use6 { // Attempt ipv6 bind, update port if successful. - sock6, newPort, err = create6(port) + sock6, newPort, err = create6(bind.listen_ip6, port) if err != nil { if originalPort == 0 && errors.Is(err, syscall.EADDRINUSE) && tries < 100 { unix.Close(sock4) @@ -159,7 +181,7 @@ again: if bind.use4 { // Attempt ipv4 bind, update port if successful. - sock4, newPort, err = create4(port) + sock4, newPort, err = create4(bind.listen_ip4, port) if err != nil { if originalPort == 0 && errors.Is(err, syscall.EADDRINUSE) && tries < 100 { unix.Close(sock6) @@ -373,7 +395,7 @@ func zoneToUint32(zone string) (uint32, error) { return uint32(n), err } -func create4(port uint16) (int, uint16, error) { +func create4(listen_ip [4]byte, port uint16) (int, uint16, error) { // create socket @@ -388,6 +410,7 @@ func create4(port uint16) (int, uint16, error) { } addr := unix.SockaddrInet4{ + Addr: listen_ip, Port: int(port), } @@ -417,7 +440,7 @@ func create4(port uint16) (int, uint16, error) { return fd, uint16(addr.Port), err } -func create6(port uint16) (int, uint16, error) { +func create6(listen_ip [16]byte, port uint16) (int, uint16, error) { // create socket @@ -434,6 +457,7 @@ func create6(port uint16) (int, uint16, error) { // set sockopts and bind addr := unix.SockaddrInet6{ + Addr: listen_ip, Port: int(port), } diff --git a/conn/bind_std.go b/conn/bind_std.go index 72bcd42..4ced9a0 100644 --- a/conn/bind_std.go +++ b/conn/bind_std.go @@ -8,6 +8,7 @@ package conn import ( "errors" "net" + "net/netip" "sync" "syscall" ) @@ -25,11 +26,13 @@ type StdNetBind struct { blackhole6 bool use4 bool use6 bool + listen_ip4 [4]byte + listen_ip6 [16]byte } func NewStdNetBind() Bind { return &StdNetBind{use4: true, use6: true, fwmark: 0} } -func NewStdNetBindAf(use4 bool, use6 bool, fwmark uint32) Bind { - return &StdNetBind{use4: use4, use6: use6, fwmark: fwmark} +func NewStdNetBindAf(use4 bool, use6 bool, listen_ip4 [4]byte, listen_ip6 [16]byte, fwmark uint32) Bind { + return &StdNetBind{use4: use4, use6: use6, fwmark: fwmark, listen_ip4: listen_ip4, listen_ip6: listen_ip6} } type StdNetEndpoint net.UDPAddr @@ -46,8 +49,8 @@ func (*StdNetEndpoint) ClearSrc() {} func (s *StdNetBind) EnabledAf() EnabledAf { return EnabledAf{ - s.use4, - s.use6, + IPv4: s.use4, + IPv6: s.use6, } } @@ -78,8 +81,8 @@ func (e *StdNetEndpoint) SrcToString() string { return "" } -func listenNet(network string, port int) (*net.UDPConn, int, error) { - conn, err := net.ListenUDP(network, &net.UDPAddr{Port: port}) +func listenNet(network string, listen_ip net.IP, port int) (*net.UDPConn, int, error) { + conn, err := net.ListenUDP(network, &net.UDPAddr{IP: listen_ip, Port: port}) if err != nil { return nil, 0, err } @@ -114,7 +117,7 @@ again: var ipv4, ipv6 *net.UDPConn if bind.use4 { - ipv4, port, err = listenNet("udp4", port) + ipv4, port, err = listenNet("udp4", netip.AddrFrom4(bind.listen_ip4).AsSlice(), port) if uport == 0 && errors.Is(err, syscall.EADDRINUSE) && tries < 100 { ipv6.Close() tries++ @@ -128,7 +131,7 @@ again: if bind.use6 { // Listen on the same port as we're using for ipv4. - ipv6, port, err = listenNet("udp6", port) + ipv6, port, err = listenNet("udp6", bind.listen_ip6[:], port) if uport == 0 && errors.Is(err, syscall.EADDRINUSE) && tries < 100 { ipv4.Close() tries++ diff --git a/conn/conn.go b/conn/conn.go index cb01584..f2d06ab 100644 --- a/conn/conn.go +++ b/conn/conn.go @@ -48,8 +48,37 @@ type Bind interface { } type EnabledAf struct { - IPv4 bool `yaml:"IPv4"` - IPv6 bool `yaml:"IPv6"` + IPv4 bool `yaml:"IPv4"` + IPv6 bool `yaml:"IPv6"` + ListenIPv4 string `yaml:"ListenIPv4"` + ListenIPv6 string `yaml:"ListenIPv6"` +} + +func (self EnabledAf) Disalbed2Enabled() EnabledAf { + return EnabledAf{ + !self.IPv4, + !self.IPv6, + self.ListenIPv4, + self.ListenIPv6, + } +} + +func (self EnabledAf) GetOnly4() EnabledAf { + return EnabledAf{ + self.IPv4, + false, + self.ListenIPv4, + "", + } +} + +func (self EnabledAf) GetOnly6() EnabledAf { + return EnabledAf{ + false, + self.IPv6, + "", + self.ListenIPv6, + } } var EnabledAf4 = EnabledAf{ diff --git a/example_config/super_mode/EgNet_edge001.yaml b/example_config/super_mode/EgNet_edge001.yaml index 1c69c61..df33460 100644 --- a/example_config/super_mode/EgNet_edge001.yaml +++ b/example_config/super_mode/EgNet_edge001.yaml @@ -18,9 +18,12 @@ DefaultTTL: 200 L2FIBTimeout: 3600 PrivKey: lyQLML+TbAZvrJpa25ARTAfMvHVQa/a1n3Wcwo7nkDU= ListenPort: 3001 +FwMark: 0 DisabledAf: IPv4: false IPv6: false + ListenIPv4: "" + ListenIPv6: "" AfPrefer: 4 LogLevel: LogLevel: error diff --git a/example_config/super_mode/EgNet_edge002.yaml b/example_config/super_mode/EgNet_edge002.yaml index 86293c1..b2d4910 100644 --- a/example_config/super_mode/EgNet_edge002.yaml +++ b/example_config/super_mode/EgNet_edge002.yaml @@ -18,9 +18,12 @@ DefaultTTL: 200 L2FIBTimeout: 3600 PrivKey: r6vMkwreEkbpXoaHgdecPuWhaVK4qWlKazgQbYPDSQ4= ListenPort: 3002 +FwMark: 0 DisabledAf: IPv4: false IPv6: false + ListenIPv4: "" + ListenIPv6: "" AfPrefer: 4 LogLevel: LogLevel: error diff --git a/example_config/super_mode/EgNet_edge100.yaml b/example_config/super_mode/EgNet_edge100.yaml index f195b3c..d96a906 100644 --- a/example_config/super_mode/EgNet_edge100.yaml +++ b/example_config/super_mode/EgNet_edge100.yaml @@ -18,9 +18,12 @@ DefaultTTL: 200 L2FIBTimeout: 3600 PrivKey: U68wDkoic4xviKbOed9EBykI/wgpfpHGmc8N4ML5spE= ListenPort: 0 +FwMark: 0 DisabledAf: IPv4: false IPv6: false + ListenIPv4: "" + ListenIPv6: "" AfPrefer: 4 LogLevel: LogLevel: error diff --git a/example_config/super_mode/EgNet_super.yaml b/example_config/super_mode/EgNet_super.yaml index 5f729b2..435bff8 100644 --- a/example_config/super_mode/EgNet_super.yaml +++ b/example_config/super_mode/EgNet_super.yaml @@ -5,6 +5,12 @@ PrivKeyV6: xUJ4yaVl/O//PRS24UFMNXgmeF/rhykroCxdJrljFgE= ListenPort: 3456 ListenPort_EdgeAPI: "3456" ListenPort_ManageAPI: "3456" +FwMark: 0 +DisabledAf: + IPv4: false + IPv6: false + ListenIPv4: "" + ListenIPv6: "" API_Prefix: /eg_net/eg_api RePushConfigInterval: 30 HttpPostInterval: 50 diff --git a/main_edge.go b/main_edge.go index 19d254b..e206239 100644 --- a/main_edge.go +++ b/main_edge.go @@ -120,10 +120,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) ( } graph.SetNHTable(econfig.NextHopTable) - EnabledAf := conn.EnabledAf{ - IPv4: !econfig.DisableAf.IPv4, - IPv6: !econfig.DisableAf.IPv6, - } + EnabledAf := econfig.DisableAf.Disalbed2Enabled() the_device := device.NewDevice(thetap, econfig.NodeID, conn.NewDefaultBind(EnabledAf, bindmode, econfig.FwMark), logger, graph, false, configPath, &econfig, nil, nil, Version) defer the_device.Close() @@ -181,7 +178,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) ( StaticSuper = false } } - err = peer.SetEndpointFromConnURL(econfig.DynamicRoute.SuperNode.EndpointV4, conn.EnabledAf4, 0, StaticSuper) + err = peer.SetEndpointFromConnURL(econfig.DynamicRoute.SuperNode.EndpointV4, EnabledAf.GetOnly4(), 0, StaticSuper) if err != nil { logger.Errorf("Failed to set endpoint for supernode v4 %v: %v", econfig.DynamicRoute.SuperNode.EndpointV4, err) S4 = false @@ -211,7 +208,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) ( StaticSuper = false } } - err = peer.SetEndpointFromConnURL(econfig.DynamicRoute.SuperNode.EndpointV6, conn.EnabledAf6, 0, StaticSuper) + err = peer.SetEndpointFromConnURL(econfig.DynamicRoute.SuperNode.EndpointV6, EnabledAf.GetOnly6(), 0, StaticSuper) if err != nil { logger.Errorf("Failed to set endpoint for supernode v6 %v: %v", econfig.DynamicRoute.SuperNode.EndpointV6, err) S6 = false diff --git a/main_super.go b/main_super.go index 181fa1e..9019d1f 100644 --- a/main_super.go +++ b/main_super.go @@ -121,6 +121,14 @@ func Super(configPath string, useUAPI bool, printExample bool, bindmode string) fmt.Sprintf("(%s) ", NodeName+"_v6"), ) + EnabledAf := sconfig.DisableAf.Disalbed2Enabled() + if !EnabledAf.IPv4 { + sconfig.PrivKeyV4 = "" + } + if !EnabledAf.IPv6 { + sconfig.PrivKeyV6 = "" + } + httpobj.http_sconfig_path = configPath httpobj.http_PeerState = make(map[string]*PeerState) httpobj.http_PeerIPs = make(map[string]*HttpPeerLocalIP) @@ -144,10 +152,10 @@ func Super(configPath string, useUAPI bool, printExample bool, bindmode string) } } thetap4, _ := tap.CreateDummyTAP() - httpobj.http_device4 = device.NewDevice(thetap4, mtypes.NodeID_SuperNode, conn.NewDefaultBind(conn.EnabledAf4, bindmode, sconfig.FwMark), logger4, httpobj.http_graph, true, configPath, nil, &sconfig, httpobj.http_super_chains, Version) + httpobj.http_device4 = device.NewDevice(thetap4, mtypes.NodeID_SuperNode, conn.NewDefaultBind(EnabledAf.GetOnly4(), bindmode, sconfig.FwMark), logger4, httpobj.http_graph, true, configPath, nil, &sconfig, httpobj.http_super_chains, Version) defer httpobj.http_device4.Close() thetap6, _ := tap.CreateDummyTAP() - httpobj.http_device6 = device.NewDevice(thetap6, mtypes.NodeID_SuperNode, conn.NewDefaultBind(conn.EnabledAf6, bindmode, sconfig.FwMark), logger6, httpobj.http_graph, true, configPath, nil, &sconfig, httpobj.http_super_chains, Version) + httpobj.http_device6 = device.NewDevice(thetap6, mtypes.NodeID_SuperNode, conn.NewDefaultBind(EnabledAf.GetOnly6(), bindmode, sconfig.FwMark), logger6, httpobj.http_graph, true, configPath, nil, &sconfig, httpobj.http_super_chains, Version) defer httpobj.http_device6.Close() if sconfig.PrivKeyV4 != "" { pk4, err := device.Str2PriKey(sconfig.PrivKeyV4) diff --git a/mtypes/config.go b/mtypes/config.go index eed86b6..6891d7d 100644 --- a/mtypes/config.go +++ b/mtypes/config.go @@ -23,12 +23,12 @@ type EdgeConfig struct { Interface InterfaceConf `yaml:"Interface"` NodeID Vertex `yaml:"NodeID"` NodeName string `yaml:"NodeName"` - FwMark uint32 `yaml:"FwMark"` PostScript string `yaml:"PostScript"` DefaultTTL uint8 `yaml:"DefaultTTL"` L2FIBTimeout float64 `yaml:"L2FIBTimeout"` PrivKey string `yaml:"PrivKey"` ListenPort int `yaml:"ListenPort"` + FwMark uint32 `yaml:"FwMark"` DisableAf conn.EnabledAf `yaml:"DisabledAf"` AfPrefer int `yaml:"AfPrefer"` LogLevel LoggerInfo `yaml:"LogLevel"` @@ -40,13 +40,14 @@ type EdgeConfig struct { type SuperConfig struct { NodeName string `yaml:"NodeName"` - FwMark uint32 `yaml:"FwMark"` PostScript string `yaml:"PostScript"` PrivKeyV4 string `yaml:"PrivKeyV4"` PrivKeyV6 string `yaml:"PrivKeyV6"` ListenPort int `yaml:"ListenPort"` ListenPort_EdgeAPI string `yaml:"ListenPort_EdgeAPI"` ListenPort_ManageAPI string `yaml:"ListenPort_ManageAPI"` + FwMark uint32 `yaml:"FwMark"` + DisableAf conn.EnabledAf `yaml:"DisabledAf"` API_Prefix string `yaml:"API_Prefix"` RePushConfigInterval float64 `yaml:"RePushConfigInterval"` HttpPostInterval float64 `yaml:"HttpPostInterval"` diff --git a/version.go b/version.go index 043a4be..9efc388 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package main -var Version = "v0.3.5-f2" +var Version = "v0.3.5-f4"