Skip to content

Commit 58cec60

Browse files
authored
Merge pull request #133 from veto9292/feat/lan-ip-rpc
feat: add GetLANIP RPC method and LANIPResponse message
2 parents f2034de + 2b5f099 commit 58cec60

10 files changed

Lines changed: 1005 additions & 454 deletions

docs/hiddifyrpc.md

Lines changed: 448 additions & 233 deletions
Large diffs are not rendered by default.

v2/ezytel/ezytel.pb.go

Lines changed: 256 additions & 112 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

v2/ezytel/ezytel_service.pb.go

Lines changed: 35 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

v2/ezytel/ezytel_service_grpc.pb.go

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

v2/hcore/commands.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@ package hcore
33
import (
44
"context"
55
"fmt"
6+
"net"
67
"runtime"
8+
"strings"
79
"time"
810

911
"github.com/hiddify/hiddify-core/v2/config"
1012
"github.com/hiddify/hiddify-core/v2/db"
1113
hcommon "github.com/hiddify/hiddify-core/v2/hcommon"
1214
"github.com/sagernet/sing-box/adapter"
15+
"github.com/wlynxg/anet"
16+
1317
// "github.com/sagernet/sing-box/common/conntrack"
1418
"github.com/sagernet/sing-box/protocol/group"
1519

@@ -383,3 +387,63 @@ func (h *HiddifyInstance) UrlTest(in *UrlTestRequest) (*hcommon.Response, error)
383387
Message: "",
384388
}, nil
385389
}
390+
391+
func (s *CoreService) GetLANIP(ctx context.Context, req *hcommon.Empty) (*LANIPResponse, error) {
392+
// Use anet instead of net to bypass Android 11+ SELinux restrictions
393+
// that block direct Netlink socket binding (permission denied error).
394+
ifaces, err := anet.Interfaces()
395+
if err != nil {
396+
Log(LogLevel_ERROR, LogType_CORE, "GetLANIP failed: ", err)
397+
return &LANIPResponse{Ip: "127.0.0.1"}, nil
398+
}
399+
400+
for _, iface := range ifaces {
401+
// Filter out interfaces that are down, loopback, or point-to-point (VPN/Tunnels)
402+
if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 || iface.Flags&net.FlagPointToPoint != 0 {
403+
continue
404+
}
405+
406+
// Exclude interfaces with names typical for VPNs, TAP, or TUN devices
407+
name := strings.ToLower(iface.Name)
408+
if strings.Contains(name, "tun") || strings.Contains(name, "tap") ||
409+
strings.Contains(name, "wintun") || strings.Contains(name, "utun") ||
410+
strings.Contains(name, "vpn") || strings.Contains(name, "ppp") {
411+
continue
412+
}
413+
414+
// Retrieve addresses using anet to ensure compatibility on Android 11+
415+
addrs, err := anet.InterfaceAddrsByInterface(&iface)
416+
if err != nil {
417+
continue
418+
}
419+
420+
for _, addr := range addrs {
421+
var ip net.IP
422+
switch v := addr.(type) {
423+
case *net.IPNet:
424+
ip = v.IP
425+
case *net.IPAddr:
426+
ip = v.IP
427+
}
428+
429+
if ip == nil || ip.IsLoopback() {
430+
continue
431+
}
432+
433+
// Ensure it is a valid IPv4 address
434+
ip4 := ip.To4()
435+
if ip4 == nil {
436+
continue
437+
}
438+
439+
// Verify the IP belongs to a standard private IP range (RFC 1918)
440+
if ip4[0] == 10 ||
441+
(ip4[0] == 172 && ip4[1] >= 16 && ip4[1] <= 31) ||
442+
(ip4[0] == 192 && ip4[1] == 168) {
443+
return &LANIPResponse{Ip: ip4.String()}, nil
444+
}
445+
}
446+
}
447+
// Fallback to loopback if no physical LAN interface is found
448+
return &LANIPResponse{Ip: "127.0.0.1"}, nil
449+
}

0 commit comments

Comments
 (0)