Skip to content

Commit be863d5

Browse files
Copilotnomeguy
andcommitted
Add IsIntranetIp check to IsAbroadIp function with tests
Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com>
1 parent 754c2f0 commit be863d5

File tree

4 files changed

+147
-2
lines changed

4 files changed

+147
-2
lines changed

ip/ip.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@
1414

1515
package ip
1616

17-
import "fmt"
17+
import (
18+
"fmt"
19+
20+
"github.com/casbin/caswaf/util"
21+
)
1822

1923
func InitIpDb() {
2024
err := Init("ip/17monipdb.dat")
@@ -24,6 +28,11 @@ func InitIpDb() {
2428
}
2529

2630
func IsAbroadIp(ip string) bool {
31+
// If it's an intranet IP, it's not abroad
32+
if util.IsIntranetIp(ip) {
33+
return false
34+
}
35+
2736
info, err := Find(ip)
2837
if err != nil {
2938
fmt.Printf("error: ip = %s, error = %s\n", ip, err.Error())

ip/ip_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright 2024 The casbin Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package ip
16+
17+
import (
18+
"os"
19+
"path/filepath"
20+
"testing"
21+
)
22+
23+
func TestIsAbroadIp(t *testing.T) {
24+
// Change to the project root directory for the test
25+
wd, _ := os.Getwd()
26+
if filepath.Base(wd) == "ip" {
27+
os.Chdir("..")
28+
}
29+
30+
// Initialize the IP database
31+
InitIpDb()
32+
33+
tests := []struct {
34+
name string
35+
ip string
36+
expected bool
37+
}{
38+
// Intranet IPs should return false
39+
{"Private 10.x.x.x", "10.0.0.1", false},
40+
{"Private 192.168.x.x", "192.168.1.1", false},
41+
{"Private 172.16.x.x", "172.16.0.1", false},
42+
{"Loopback", "127.0.0.1", false},
43+
{"Link-local", "169.254.1.1", false},
44+
45+
// Note: Testing public IPs requires the IP database to be properly loaded
46+
// The actual behavior depends on the IP geolocation database content
47+
// These tests verify that intranet IPs are handled correctly
48+
}
49+
50+
for _, tt := range tests {
51+
t.Run(tt.name, func(t *testing.T) {
52+
result := IsAbroadIp(tt.ip)
53+
if result != tt.expected {
54+
t.Errorf("IsAbroadIp(%s) = %v, expected %v", tt.ip, result, tt.expected)
55+
}
56+
})
57+
}
58+
}

util/network.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@
1414

1515
package util
1616

17-
import "os"
17+
import (
18+
"net"
19+
"os"
20+
)
1821

1922
var hostname = ""
2023

@@ -30,3 +33,17 @@ func init() {
3033
func GetHostname() string {
3134
return hostname
3235
}
36+
37+
func IsIntranetIp(ip string) bool {
38+
ipStr, _, err := net.SplitHostPort(ip)
39+
if err != nil {
40+
ipStr = ip
41+
}
42+
43+
parsedIP := net.ParseIP(ipStr)
44+
if parsedIP == nil {
45+
return false
46+
}
47+
48+
return parsedIP.IsPrivate() || parsedIP.IsLoopback() || parsedIP.IsLinkLocalUnicast() || parsedIP.IsLinkLocalMulticast()
49+
}

util/network_test.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright 2023 The casbin Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package util
16+
17+
import "testing"
18+
19+
func TestIsIntranetIp(t *testing.T) {
20+
tests := []struct {
21+
name string
22+
ip string
23+
expected bool
24+
}{
25+
// Private IPv4 addresses
26+
{"Private 10.x.x.x", "10.0.0.1", true},
27+
{"Private 192.168.x.x", "192.168.1.1", true},
28+
{"Private 172.16.x.x", "172.16.0.1", true},
29+
{"Private 172.31.x.x", "172.31.255.255", true},
30+
31+
// Loopback
32+
{"Loopback IPv4", "127.0.0.1", true},
33+
{"Loopback IPv6", "::1", true},
34+
35+
// Link-local
36+
{"Link-local IPv4", "169.254.1.1", true},
37+
{"Link-local IPv6", "fe80::1", true},
38+
39+
// Public IPs
40+
{"Public Google DNS", "8.8.8.8", false},
41+
{"Public Cloudflare DNS", "1.1.1.1", false},
42+
{"Public IPv4", "123.45.67.89", false},
43+
44+
// With port
45+
{"Private with port", "192.168.1.1:8080", true},
46+
{"Public with port", "8.8.8.8:53", false},
47+
48+
// Invalid IPs
49+
{"Invalid IP", "invalid", false},
50+
{"Empty string", "", false},
51+
}
52+
53+
for _, tt := range tests {
54+
t.Run(tt.name, func(t *testing.T) {
55+
result := IsIntranetIp(tt.ip)
56+
if result != tt.expected {
57+
t.Errorf("IsIntranetIp(%s) = %v, expected %v", tt.ip, result, tt.expected)
58+
}
59+
})
60+
}
61+
}

0 commit comments

Comments
 (0)