mirror of
				https://github.com/TeaOSLab/EdgeNode.git
				synced 2025-11-04 07:40:56 +08:00 
			
		
		
		
	实现IP黑白名单、国家|地区封禁、省份封禁
This commit is contained in:
		@@ -38,6 +38,7 @@ function build() {
 | 
				
			|||||||
	cp $ROOT/configs/api.template.yaml $DIST/configs
 | 
						cp $ROOT/configs/api.template.yaml $DIST/configs
 | 
				
			||||||
	cp -R $ROOT/www $DIST/
 | 
						cp -R $ROOT/www $DIST/
 | 
				
			||||||
	cp -R $ROOT/pages $DIST/
 | 
						cp -R $ROOT/pages $DIST/
 | 
				
			||||||
 | 
						cp -R $ROOT/resources $DIST/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	echo "building ..."
 | 
						echo "building ..."
 | 
				
			||||||
	env GOOS=${OS} GOARCH=${ARCH} go build -o $DIST/bin/${NAME} -ldflags="-s -w" $ROOT/../cmd/edge-node/main.go
 | 
						env GOOS=${OS} GOARCH=${ARCH} go build -o $DIST/bin/${NAME} -ldflags="-s -w" $ROOT/../cmd/edge-node/main.go
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								build/configs/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								build/configs/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,4 @@
 | 
				
			|||||||
node.json
 | 
					node.json
 | 
				
			||||||
api.yaml
 | 
					api.yaml
 | 
				
			||||||
cluster.yaml
 | 
					cluster.yaml
 | 
				
			||||||
 | 
					*.cache
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								build/resources/ipdata/ip2region/ip2region.db
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								build/resources/ipdata/ip2region/ip2region.db
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							@@ -13,6 +13,7 @@ require (
 | 
				
			|||||||
	github.com/go-yaml/yaml v2.1.0+incompatible
 | 
						github.com/go-yaml/yaml v2.1.0+incompatible
 | 
				
			||||||
	github.com/golang/protobuf v1.4.2
 | 
						github.com/golang/protobuf v1.4.2
 | 
				
			||||||
	github.com/iwind/TeaGo v0.0.0-20201020081413-7cf62d6f420f
 | 
						github.com/iwind/TeaGo v0.0.0-20201020081413-7cf62d6f420f
 | 
				
			||||||
 | 
						github.com/lionsoul2014/ip2region v2.2.0-release+incompatible
 | 
				
			||||||
	github.com/shirou/gopsutil v2.20.9+incompatible
 | 
						github.com/shirou/gopsutil v2.20.9+incompatible
 | 
				
			||||||
	golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7
 | 
						golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7
 | 
				
			||||||
	google.golang.org/grpc v1.32.0
 | 
						google.golang.org/grpc v1.32.0
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
								
							@@ -29,6 +29,7 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
 | 
				
			|||||||
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
 | 
					github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
 | 
				
			||||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
 | 
					github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
 | 
				
			||||||
github.com/go-redis/redis/v8 v8.0.0-beta.7/go.mod h1:FGJAWDWFht1sQ4qxyJHZZbVyvnVcKQN0E3u5/5lRz+g=
 | 
					github.com/go-redis/redis/v8 v8.0.0-beta.7/go.mod h1:FGJAWDWFht1sQ4qxyJHZZbVyvnVcKQN0E3u5/5lRz+g=
 | 
				
			||||||
 | 
					github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
 | 
				
			||||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
 | 
					github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
 | 
				
			||||||
github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
 | 
					github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
 | 
				
			||||||
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
 | 
					github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
 | 
				
			||||||
@@ -64,6 +65,9 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
 | 
				
			|||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 | 
					github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 | 
				
			||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 | 
					github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 | 
				
			||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 | 
					github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 | 
				
			||||||
 | 
					github.com/lionsoul2014/ip2region v1.9.0-release h1:b4FxevWljlOb+Z3qtAMQIvel6az21p7OeZ0K1wn/3mI=
 | 
				
			||||||
 | 
					github.com/lionsoul2014/ip2region v2.2.0-release+incompatible h1:1qp9iks+69h7IGLazAplzS9Ca14HAxuD5c0rbFdPGy4=
 | 
				
			||||||
 | 
					github.com/lionsoul2014/ip2region v2.2.0-release+incompatible/go.mod h1:+ZBN7PBoh5gG6/y0ZQ85vJDBe21WnfbRrQQwTfliJJI=
 | 
				
			||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
 | 
					github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
 | 
				
			||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
					github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
				
			||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 | 
					github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,5 +3,6 @@ package events
 | 
				
			|||||||
type Event = string
 | 
					type Event = string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	EventQuit Event = "quit" // quit node gracefully
 | 
						EventStart Event = "start" // start loading
 | 
				
			||||||
 | 
						EventQuit  Event = "quit"  // quit node gracefully
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -84,7 +84,7 @@ func (this *Grid) WriteInt64(key []byte, value int64, lifeSeconds int64) {
 | 
				
			|||||||
		Key:        key,
 | 
							Key:        key,
 | 
				
			||||||
		Type:       ItemInt64,
 | 
							Type:       ItemInt64,
 | 
				
			||||||
		ValueInt64: value,
 | 
							ValueInt64: value,
 | 
				
			||||||
		ExpireAt:   time.Now().Unix() + lifeSeconds,
 | 
							ExpireAt:   UnixTime() + lifeSeconds,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,9 +61,12 @@ func TestMemoryGrid_Compress(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func BenchmarkMemoryGrid_Performance(b *testing.B) {
 | 
					func BenchmarkMemoryGrid_Performance(b *testing.B) {
 | 
				
			||||||
 | 
						runtime.GOMAXPROCS(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	grid := NewGrid(1024)
 | 
						grid := NewGrid(1024)
 | 
				
			||||||
	for i := 0; i < b.N; i++ {
 | 
						for i := 0; i < b.N; i++ {
 | 
				
			||||||
		grid.WriteInt64([]byte("key:"+strconv.Itoa(i)), int64(i), 3600)
 | 
							key := "key:" + strconv.Itoa(i)
 | 
				
			||||||
 | 
							grid.WriteInt64([]byte(key), int64(i), 3600)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										26
									
								
								internal/grids/time.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								internal/grids/time.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					package grids
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var unixTime = time.Now().Unix()
 | 
				
			||||||
 | 
					var unixTimerIsReady = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						ticker := time.NewTicker(500 * time.Millisecond)
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							for range ticker.C {
 | 
				
			||||||
 | 
								unixTimerIsReady = true
 | 
				
			||||||
 | 
								unixTime = time.Now().Unix()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 最快获取时间戳的方式,通常用在不需要特别精确时间戳的场景
 | 
				
			||||||
 | 
					func UnixTime() int64 {
 | 
				
			||||||
 | 
						if unixTimerIsReady {
 | 
				
			||||||
 | 
							return unixTime
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return time.Now().Unix()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								internal/grids/time_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								internal/grids/time_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					package grids
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestUnixTime(t *testing.T) {
 | 
				
			||||||
 | 
						for i := 0; i < 5; i++ {
 | 
				
			||||||
 | 
							t.Log(UnixTime(), "real:", time.Now().Unix())
 | 
				
			||||||
 | 
							time.Sleep(1 * time.Second)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										5
									
								
								internal/iplibrary/init.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								internal/iplibrary/init.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								internal/iplibrary/ip_item.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								internal/iplibrary/ip_item.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/TeaOSLab/EdgeNode/internal/utils"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type IPItem struct {
 | 
				
			||||||
 | 
						Id        int64
 | 
				
			||||||
 | 
						IPFrom    uint32
 | 
				
			||||||
 | 
						IPTo      uint32
 | 
				
			||||||
 | 
						ExpiredAt int64
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *IPItem) Contains(ip uint32) bool {
 | 
				
			||||||
 | 
						if this.IPTo == 0 {
 | 
				
			||||||
 | 
							if this.IPFrom != ip {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if this.IPFrom > ip || this.IPTo < ip {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if this.ExpiredAt > 0 && this.ExpiredAt < utils.UnixTime() {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										73
									
								
								internal/iplibrary/ip_item_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								internal/iplibrary/ip_item_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/assert"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestIPItem_Contains(t *testing.T) {
 | 
				
			||||||
 | 
						a := assert.NewAssertion(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							item := &IPItem{
 | 
				
			||||||
 | 
								IPFrom:    IP2Long("192.168.1.100"),
 | 
				
			||||||
 | 
								IPTo:      0,
 | 
				
			||||||
 | 
								ExpiredAt: 0,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							a.IsTrue(item.Contains(IP2Long("192.168.1.100")))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							item := &IPItem{
 | 
				
			||||||
 | 
								IPFrom:    IP2Long("192.168.1.100"),
 | 
				
			||||||
 | 
								IPTo:      0,
 | 
				
			||||||
 | 
								ExpiredAt: time.Now().Unix() + 1,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							a.IsTrue(item.Contains(IP2Long("192.168.1.100")))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							item := &IPItem{
 | 
				
			||||||
 | 
								IPFrom:    IP2Long("192.168.1.100"),
 | 
				
			||||||
 | 
								IPTo:      0,
 | 
				
			||||||
 | 
								ExpiredAt: time.Now().Unix() - 1,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							a.IsFalse(item.Contains(IP2Long("192.168.1.100")))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							item := &IPItem{
 | 
				
			||||||
 | 
								IPFrom:    IP2Long("192.168.1.100"),
 | 
				
			||||||
 | 
								IPTo:      0,
 | 
				
			||||||
 | 
								ExpiredAt: 0,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							a.IsFalse(item.Contains(IP2Long("192.168.1.101")))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							item := &IPItem{
 | 
				
			||||||
 | 
								IPFrom:    IP2Long("192.168.1.1"),
 | 
				
			||||||
 | 
								IPTo:      IP2Long("192.168.1.101"),
 | 
				
			||||||
 | 
								ExpiredAt: 0,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							a.IsTrue(item.Contains(IP2Long("192.168.1.100")))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							item := &IPItem{
 | 
				
			||||||
 | 
								IPFrom:    IP2Long("192.168.1.1"),
 | 
				
			||||||
 | 
								IPTo:      IP2Long("192.168.1.100"),
 | 
				
			||||||
 | 
								ExpiredAt: 0,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							a.IsTrue(item.Contains(IP2Long("192.168.1.100")))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							item := &IPItem{
 | 
				
			||||||
 | 
								IPFrom:    IP2Long("192.168.1.1"),
 | 
				
			||||||
 | 
								IPTo:      IP2Long("192.168.1.101"),
 | 
				
			||||||
 | 
								ExpiredAt: 0,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							a.IsTrue(item.Contains(IP2Long("192.168.1.1")))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										45
									
								
								internal/iplibrary/ip_list.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								internal/iplibrary/ip_list.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IP名单
 | 
				
			||||||
 | 
					type IPList struct {
 | 
				
			||||||
 | 
						itemsMap map[int64]*IPItem // id => item
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						locker sync.RWMutex
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewIPList() *IPList {
 | 
				
			||||||
 | 
						return &IPList{
 | 
				
			||||||
 | 
							itemsMap: map[int64]*IPItem{},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *IPList) Add(item *IPItem) {
 | 
				
			||||||
 | 
						this.locker.Lock()
 | 
				
			||||||
 | 
						this.itemsMap[item.Id] = item
 | 
				
			||||||
 | 
						this.locker.Unlock()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *IPList) Delete(itemId int64) {
 | 
				
			||||||
 | 
						this.locker.Lock()
 | 
				
			||||||
 | 
						delete(this.itemsMap, itemId)
 | 
				
			||||||
 | 
						this.locker.Unlock()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 判断是否包含某个IP
 | 
				
			||||||
 | 
					func (this *IPList) Contains(ip uint32) bool {
 | 
				
			||||||
 | 
						// TODO 优化查询速度,可能需要把items分成两组,一组是单个的,一组是按照范围的,按照范围的再进行二分法查找
 | 
				
			||||||
 | 
						this.locker.RLock()
 | 
				
			||||||
 | 
						for _, item := range this.itemsMap {
 | 
				
			||||||
 | 
							if item.Contains(ip) {
 | 
				
			||||||
 | 
								this.locker.RUnlock()
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this.locker.RUnlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										53
									
								
								internal/iplibrary/ip_list_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								internal/iplibrary/ip_list_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"runtime"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNewIPList_Memory(t *testing.T) {
 | 
				
			||||||
 | 
						list := NewIPList()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < 200_0000; i++ {
 | 
				
			||||||
 | 
							list.Add(&IPItem{
 | 
				
			||||||
 | 
								IPFrom:    1,
 | 
				
			||||||
 | 
								IPTo:      2,
 | 
				
			||||||
 | 
								ExpiredAt: time.Now().Unix(),
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Log("ok")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestIPList_Contains(t *testing.T) {
 | 
				
			||||||
 | 
						list := NewIPList()
 | 
				
			||||||
 | 
						for i := 0; i < 255; i++ {
 | 
				
			||||||
 | 
							list.Add(&IPItem{
 | 
				
			||||||
 | 
								Id:        int64(i),
 | 
				
			||||||
 | 
								IPFrom:    IP2Long("192.168.1." + strconv.Itoa(i)),
 | 
				
			||||||
 | 
								IPTo:      0,
 | 
				
			||||||
 | 
								ExpiredAt: 0,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.Log(list.Contains(IP2Long("192.168.1.100")))
 | 
				
			||||||
 | 
						t.Log(list.Contains(IP2Long("192.168.2.100")))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func BenchmarkIPList_Contains(b *testing.B) {
 | 
				
			||||||
 | 
						runtime.GOMAXPROCS(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list := NewIPList()
 | 
				
			||||||
 | 
						for i := 0; i < 10_000; i++ {
 | 
				
			||||||
 | 
							list.Add(&IPItem{
 | 
				
			||||||
 | 
								Id:        int64(i),
 | 
				
			||||||
 | 
								IPFrom:    IP2Long("192.168.1." + strconv.Itoa(i)),
 | 
				
			||||||
 | 
								IPTo:      0,
 | 
				
			||||||
 | 
								ExpiredAt: time.Now().Unix() + 60,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i := 0; i < b.N; i++ {
 | 
				
			||||||
 | 
							_ = list.Contains(IP2Long("192.168.1.100"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								internal/iplibrary/ip_utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								internal/iplibrary/ip_utils.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/binary"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 将IP转换为整型
 | 
				
			||||||
 | 
					func IP2Long(ip string) uint32 {
 | 
				
			||||||
 | 
						s := net.ParseIP(ip)
 | 
				
			||||||
 | 
						if s == nil {
 | 
				
			||||||
 | 
							return 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(s) == 16 {
 | 
				
			||||||
 | 
							return binary.BigEndian.Uint32(s[12:16])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return binary.BigEndian.Uint32(s)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										21
									
								
								internal/iplibrary/ip_utils_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/iplibrary/ip_utils_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"runtime"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestIP2Long(t *testing.T) {
 | 
				
			||||||
 | 
						t.Log(IP2Long("192.168.1.100"))
 | 
				
			||||||
 | 
						t.Log(IP2Long("192.168.1.101"))
 | 
				
			||||||
 | 
						t.Log(IP2Long("202.106.0.20"))
 | 
				
			||||||
 | 
						t.Log(IP2Long("192.168.1")) // wrong ip, should return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func BenchmarkIP2Long(b *testing.B) {
 | 
				
			||||||
 | 
						runtime.GOMAXPROCS(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < b.N; i++ {
 | 
				
			||||||
 | 
							_ = IP2Long("192.168.1.100")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										12
									
								
								internal/iplibrary/library_interface.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								internal/iplibrary/library_interface.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type LibraryInterface interface {
 | 
				
			||||||
 | 
						// 加载数据库文件
 | 
				
			||||||
 | 
						Load(dbPath string) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 查询IP
 | 
				
			||||||
 | 
						Lookup(ip string) (*Result, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 关闭数据库文件
 | 
				
			||||||
 | 
						Close()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										72
									
								
								internal/iplibrary/library_ip2region.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								internal/iplibrary/library_ip2region.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/errors"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/logs"
 | 
				
			||||||
 | 
						"github.com/lionsoul2014/ip2region/binding/golang/ip2region"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type IP2RegionLibrary struct {
 | 
				
			||||||
 | 
						db *ip2region.Ip2Region
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *IP2RegionLibrary) Load(dbPath string) error {
 | 
				
			||||||
 | 
						db, err := ip2region.New(dbPath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this.db = db
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *IP2RegionLibrary) Lookup(ip string) (*Result, error) {
 | 
				
			||||||
 | 
						if this.db == nil {
 | 
				
			||||||
 | 
							return nil, errors.New("library has not been loaded")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							// 防止panic发生
 | 
				
			||||||
 | 
							err := recover()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								logs.Println("[IP2RegionLibrary]panic: " + fmt.Sprintf("%#v", err))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						info, err := this.db.MemorySearch(ip)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if info.Country == "0" {
 | 
				
			||||||
 | 
							info.Country = ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if info.Region == "0" {
 | 
				
			||||||
 | 
							info.Region = ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if info.Province == "0" {
 | 
				
			||||||
 | 
							info.Province = ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if info.City == "0" {
 | 
				
			||||||
 | 
							info.City = ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if info.ISP == "0" {
 | 
				
			||||||
 | 
							info.ISP = ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &Result{
 | 
				
			||||||
 | 
							CityId:   info.CityId,
 | 
				
			||||||
 | 
							Country:  info.Country,
 | 
				
			||||||
 | 
							Region:   info.Region,
 | 
				
			||||||
 | 
							Province: info.Province,
 | 
				
			||||||
 | 
							City:     info.City,
 | 
				
			||||||
 | 
							ISP:      info.ISP,
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *IP2RegionLibrary) Close() {
 | 
				
			||||||
 | 
						if this.db != nil {
 | 
				
			||||||
 | 
							this.db.Close()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										55
									
								
								internal/iplibrary/library_ip2region_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								internal/iplibrary/library_ip2region_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/Tea"
 | 
				
			||||||
 | 
						_ "github.com/iwind/TeaGo/bootstrap"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/logs"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/rands"
 | 
				
			||||||
 | 
						"runtime"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestIP2RegionLibrary_Lookup(t *testing.T) {
 | 
				
			||||||
 | 
						library := &IP2RegionLibrary{}
 | 
				
			||||||
 | 
						err := library.Load(Tea.Root + "/resources/ipdata/ip2region/ip2region.db")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						result, err := library.Lookup("114.240.223.47")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						logs.PrintAsJSON(result, t)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestIP2RegionLibrary_Memory(t *testing.T) {
 | 
				
			||||||
 | 
						library := &IP2RegionLibrary{}
 | 
				
			||||||
 | 
						err := library.Load(Tea.Root + "/resources/ipdata/ip2region/ip2region.db")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						before := time.Now()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < 1_000_000; i++ {
 | 
				
			||||||
 | 
							_, _ = library.Lookup(strconv.Itoa(rands.Int(0, 254)) + "." + strconv.Itoa(rands.Int(0, 254)) + "." + strconv.Itoa(rands.Int(0, 254)) + "." + strconv.Itoa(rands.Int(0, 254)))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Log("cost:", time.Since(before).Seconds()*1000, "ms")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func BenchmarkIP2RegionLibrary_Lookup(b *testing.B) {
 | 
				
			||||||
 | 
						runtime.GOMAXPROCS(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						library := &IP2RegionLibrary{}
 | 
				
			||||||
 | 
						err := library.Load(Tea.Root + "/resources/ipdata/ip2region/ip2region.db")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							b.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < b.N; i++ {
 | 
				
			||||||
 | 
							_, _ = library.Lookup(strconv.Itoa(rands.Int(0, 254)) + "." + strconv.Itoa(rands.Int(0, 254)) + "." + strconv.Itoa(rands.Int(0, 254)) + "." + strconv.Itoa(rands.Int(0, 254)))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										95
									
								
								internal/iplibrary/manager.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								internal/iplibrary/manager.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/errors"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/events"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/Tea"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/files"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/logs"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/types"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var SharedManager = NewManager()
 | 
				
			||||||
 | 
					var SharedLibrary LibraryInterface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						events.On(events.EventStart, func() {
 | 
				
			||||||
 | 
							// 初始化
 | 
				
			||||||
 | 
							library, err := SharedManager.Load()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								logs.Println("[IP_LIBRARY]" + err.Error())
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							SharedLibrary = library
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Manager struct {
 | 
				
			||||||
 | 
						code string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewManager() *Manager {
 | 
				
			||||||
 | 
						return &Manager{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *Manager) Load() (LibraryInterface, error) {
 | 
				
			||||||
 | 
						nodeConfig, err := nodeconfigs.SharedNodeConfig()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						config := nodeConfig.GlobalConfig
 | 
				
			||||||
 | 
						if config == nil {
 | 
				
			||||||
 | 
							config = &serverconfigs.GlobalConfig{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 当前正在使用的IP库代号
 | 
				
			||||||
 | 
						code := config.IPLibrary.Code
 | 
				
			||||||
 | 
						if len(code) == 0 {
 | 
				
			||||||
 | 
							code = serverconfigs.DefaultIPLibraryType
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						dir := Tea.Root + "/resources/ipdata/" + code
 | 
				
			||||||
 | 
						var lastVersion int64 = -1
 | 
				
			||||||
 | 
						lastFilename := ""
 | 
				
			||||||
 | 
						for _, file := range files.NewFile(dir).List() {
 | 
				
			||||||
 | 
							filename := file.Name()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							reg := regexp.MustCompile(`^` + regexp.QuoteMeta(code) + `.(\d+)\.`)
 | 
				
			||||||
 | 
							if reg.MatchString(filename) { // 先查找有版本号的
 | 
				
			||||||
 | 
								result := reg.FindStringSubmatch(filename)
 | 
				
			||||||
 | 
								version := types.Int64(result[1])
 | 
				
			||||||
 | 
								if version > lastVersion {
 | 
				
			||||||
 | 
									lastVersion = version
 | 
				
			||||||
 | 
									lastFilename = filename
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if strings.HasPrefix(filename, code+".") { // 后查找默认的
 | 
				
			||||||
 | 
								if lastVersion == -1 {
 | 
				
			||||||
 | 
									lastFilename = filename
 | 
				
			||||||
 | 
									lastVersion = 0
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(lastFilename) == 0 {
 | 
				
			||||||
 | 
							return nil, errors.New("ip library file not found")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var libraryPtr LibraryInterface
 | 
				
			||||||
 | 
						switch code {
 | 
				
			||||||
 | 
						case serverconfigs.IPLibraryTypeIP2Region:
 | 
				
			||||||
 | 
							libraryPtr = &IP2RegionLibrary{}
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return nil, errors.New("invalid ip library code '" + code + "'")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = libraryPtr.Load(dir + "/" + lastFilename)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return libraryPtr, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										137
									
								
								internal/iplibrary/manager_country.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								internal/iplibrary/manager_country.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,137 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/md5"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/events"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/logs"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/rpc"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/utils"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/Tea"
 | 
				
			||||||
 | 
						_ "github.com/iwind/TeaGo/bootstrap"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var SharedCountryManager = NewCountryManager()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						events.On(events.EventStart, func() {
 | 
				
			||||||
 | 
							go SharedCountryManager.Start()
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 国家信息管理
 | 
				
			||||||
 | 
					type CountryManager struct {
 | 
				
			||||||
 | 
						cacheFile string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						countryMap map[string]int64 // countryName => countryId
 | 
				
			||||||
 | 
						dataHash   string           // 国家JSON的md5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						locker sync.RWMutex
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewCountryManager() *CountryManager {
 | 
				
			||||||
 | 
						return &CountryManager{
 | 
				
			||||||
 | 
							cacheFile:  Tea.Root + "/configs/region_country.json.cache",
 | 
				
			||||||
 | 
							countryMap: map[string]int64{},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *CountryManager) Start() {
 | 
				
			||||||
 | 
						// 从缓存中读取
 | 
				
			||||||
 | 
						err := this.load()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							logs.Error("COUNTRY_MANAGER", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 第一次更新
 | 
				
			||||||
 | 
						err = this.loop()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							logs.Error("COUNTRY_MANAGER", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 定时更新
 | 
				
			||||||
 | 
						ticker := utils.NewTicker(1 * time.Hour)
 | 
				
			||||||
 | 
						events.On(events.EventQuit, func() {
 | 
				
			||||||
 | 
							ticker.Stop()
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						for range ticker.C {
 | 
				
			||||||
 | 
							err := this.loop()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								logs.Error("COUNTRY_MANAGER", err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *CountryManager) Lookup(countryName string) (countryId int64) {
 | 
				
			||||||
 | 
						this.locker.RLock()
 | 
				
			||||||
 | 
						countryId, _ = this.countryMap[countryName]
 | 
				
			||||||
 | 
						this.locker.RUnlock()
 | 
				
			||||||
 | 
						return countryId
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 从缓存中读取
 | 
				
			||||||
 | 
					func (this *CountryManager) load() error {
 | 
				
			||||||
 | 
						data, err := ioutil.ReadFile(this.cacheFile)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if os.IsNotExist(err) {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m := map[string]int64{}
 | 
				
			||||||
 | 
						err = json.Unmarshal(data, &m)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if m != nil && len(m) > 0 {
 | 
				
			||||||
 | 
							this.countryMap = m
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 更新国家信息
 | 
				
			||||||
 | 
					func (this *CountryManager) loop() error {
 | 
				
			||||||
 | 
						rpcClient, err := rpc.SharedRPC()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						resp, err := rpcClient.RegionCountryRPC().FindAllEnabledRegionCountries(rpcClient.Context(), &pb.FindAllEnabledRegionCountriesRequest{})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m := map[string]int64{}
 | 
				
			||||||
 | 
						for _, country := range resp.Countries {
 | 
				
			||||||
 | 
							for _, code := range country.Codes {
 | 
				
			||||||
 | 
								m[code] = country.Id
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 检查是否有更新
 | 
				
			||||||
 | 
						data, err := json.Marshal(m)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						hash := md5.New()
 | 
				
			||||||
 | 
						hash.Write(data)
 | 
				
			||||||
 | 
						dataHash := fmt.Sprintf("%x", hash.Sum(nil))
 | 
				
			||||||
 | 
						if this.dataHash == dataHash {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this.dataHash = dataHash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.locker.Lock()
 | 
				
			||||||
 | 
						this.countryMap = m
 | 
				
			||||||
 | 
						this.locker.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 保存到本地缓存
 | 
				
			||||||
 | 
						err = ioutil.WriteFile(this.cacheFile, data, 0666)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										57
									
								
								internal/iplibrary/manager_country_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								internal/iplibrary/manager_country_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"runtime"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestCountryManager_load(t *testing.T) {
 | 
				
			||||||
 | 
						manager := NewCountryManager()
 | 
				
			||||||
 | 
						err := manager.load()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.Log("ok", manager.countryMap)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestCountryManager_loop(t *testing.T) {
 | 
				
			||||||
 | 
						manager := NewCountryManager()
 | 
				
			||||||
 | 
						err := manager.loop()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.Log("ok", manager.countryMap)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestCountryManager_loop_skip(t *testing.T) {
 | 
				
			||||||
 | 
						manager := NewCountryManager()
 | 
				
			||||||
 | 
						for i := 0; i < 10; i++ {
 | 
				
			||||||
 | 
							err := manager.loop()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestCountryManager_Lookup(t *testing.T) {
 | 
				
			||||||
 | 
						manager := NewCountryManager()
 | 
				
			||||||
 | 
						err := manager.load()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.Log(manager.Lookup("中国"), manager.Lookup("美国 "))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func BenchmarkCountryManager_Lookup(b *testing.B) {
 | 
				
			||||||
 | 
						runtime.GOMAXPROCS(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						manager := NewCountryManager()
 | 
				
			||||||
 | 
						err := manager.load()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							b.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < b.N; i++ {
 | 
				
			||||||
 | 
							_ = manager.Lookup("中国")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										124
									
								
								internal/iplibrary/manager_ip_list.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								internal/iplibrary/manager_ip_list.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/events"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/logs"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/rpc"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/Tea"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var SharedIPListManager = NewIPListManager()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						events.On(events.EventStart, func() {
 | 
				
			||||||
 | 
							go SharedIPListManager.Start()
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IP名单管理
 | 
				
			||||||
 | 
					type IPListManager struct {
 | 
				
			||||||
 | 
						// 缓存文件
 | 
				
			||||||
 | 
						// 每行一个数据:id|from|to|expiredAt
 | 
				
			||||||
 | 
						cacheFile string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						version  int64
 | 
				
			||||||
 | 
						pageSize int64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						listMap map[int64]*IPList
 | 
				
			||||||
 | 
						locker  sync.Mutex
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewIPListManager() *IPListManager {
 | 
				
			||||||
 | 
						return &IPListManager{
 | 
				
			||||||
 | 
							cacheFile: Tea.Root + "/configs/ip_list.cache",
 | 
				
			||||||
 | 
							pageSize:  1000,
 | 
				
			||||||
 | 
							listMap:   map[int64]*IPList{},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *IPListManager) Start() {
 | 
				
			||||||
 | 
						// TODO 从缓存当中读取数据
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 第一次读取
 | 
				
			||||||
 | 
						err := this.loop()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							logs.Println("IP_LIST_MANAGER", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ticker := time.NewTicker(60 * time.Second) // TODO 未来改成可以手动触发IP变更事件
 | 
				
			||||||
 | 
						events.On(events.EventQuit, func() {
 | 
				
			||||||
 | 
							ticker.Stop()
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						for range ticker.C {
 | 
				
			||||||
 | 
							err := this.loop()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								logs.Println("IP_LIST_MANAGER", err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *IPListManager) loop() error {
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							hasNext, err := this.fetch()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !hasNext {
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO 写入到缓存当中
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *IPListManager) fetch() (hasNext bool, err error) {
 | 
				
			||||||
 | 
						rpcClient, err := rpc.SharedRPC()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						itemsResp, err := rpcClient.IPItemRPC().ListIPItemsAfterVersion(rpcClient.Context(), &pb.ListIPItemsAfterVersionRequest{
 | 
				
			||||||
 | 
							Version: this.version,
 | 
				
			||||||
 | 
							Size:    this.pageSize,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						items := itemsResp.IpItems
 | 
				
			||||||
 | 
						if len(items) == 0 {
 | 
				
			||||||
 | 
							return false, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this.locker.Lock()
 | 
				
			||||||
 | 
						for _, item := range items {
 | 
				
			||||||
 | 
							list, ok := this.listMap[item.ListId]
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								list = NewIPList()
 | 
				
			||||||
 | 
								this.listMap[item.ListId] = list
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if item.IsDeleted {
 | 
				
			||||||
 | 
								list.Delete(item.Id)
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							list.Add(&IPItem{
 | 
				
			||||||
 | 
								Id:        item.Id,
 | 
				
			||||||
 | 
								IPFrom:    IP2Long(item.IpFrom),
 | 
				
			||||||
 | 
								IPTo:      IP2Long(item.IpTo),
 | 
				
			||||||
 | 
								ExpiredAt: item.ExpiredAt,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this.locker.Unlock()
 | 
				
			||||||
 | 
						this.version = items[len(items)-1].Version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *IPListManager) FindList(listId int64) *IPList {
 | 
				
			||||||
 | 
						this.locker.Lock()
 | 
				
			||||||
 | 
						list, _ := this.listMap[listId]
 | 
				
			||||||
 | 
						this.locker.Unlock()
 | 
				
			||||||
 | 
						return list
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										12
									
								
								internal/iplibrary/manager_ip_list_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								internal/iplibrary/manager_ip_list_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestIPListManager_loop(t *testing.T) {
 | 
				
			||||||
 | 
						manager := NewIPListManager()
 | 
				
			||||||
 | 
						manager.pageSize = 2
 | 
				
			||||||
 | 
						err := manager.loop()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										144
									
								
								internal/iplibrary/manager_province.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								internal/iplibrary/manager_province.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,144 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/md5"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/events"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/logs"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/rpc"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/utils"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/Tea"
 | 
				
			||||||
 | 
						_ "github.com/iwind/TeaGo/bootstrap"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						ChinaCountryId int64 = 1
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var SharedProvinceManager = NewProvinceManager()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						events.On(events.EventStart, func() {
 | 
				
			||||||
 | 
							go SharedProvinceManager.Start()
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 国家信息管理
 | 
				
			||||||
 | 
					type ProvinceManager struct {
 | 
				
			||||||
 | 
						cacheFile string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						provinceMap map[string]int64 // provinceName => provinceId
 | 
				
			||||||
 | 
						dataHash    string           // 国家JSON的md5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						locker sync.RWMutex
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewProvinceManager() *ProvinceManager {
 | 
				
			||||||
 | 
						return &ProvinceManager{
 | 
				
			||||||
 | 
							cacheFile:   Tea.Root + "/configs/region_province.json.cache",
 | 
				
			||||||
 | 
							provinceMap: map[string]int64{},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *ProvinceManager) Start() {
 | 
				
			||||||
 | 
						// 从缓存中读取
 | 
				
			||||||
 | 
						err := this.load()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							logs.Error("PROVINCE_MANAGER", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 第一次更新
 | 
				
			||||||
 | 
						err = this.loop()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							logs.Error("PROVINCE_MANAGER", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 定时更新
 | 
				
			||||||
 | 
						ticker := utils.NewTicker(1 * time.Hour)
 | 
				
			||||||
 | 
						events.On(events.EventQuit, func() {
 | 
				
			||||||
 | 
							ticker.Stop()
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						for range ticker.C {
 | 
				
			||||||
 | 
							err := this.loop()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								logs.Error("PROVINCE_MANAGER", err.Error())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *ProvinceManager) Lookup(provinceName string) (provinceId int64) {
 | 
				
			||||||
 | 
						this.locker.RLock()
 | 
				
			||||||
 | 
						provinceId, _ = this.provinceMap[provinceName]
 | 
				
			||||||
 | 
						this.locker.RUnlock()
 | 
				
			||||||
 | 
						return provinceId
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 从缓存中读取
 | 
				
			||||||
 | 
					func (this *ProvinceManager) load() error {
 | 
				
			||||||
 | 
						data, err := ioutil.ReadFile(this.cacheFile)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if os.IsNotExist(err) {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m := map[string]int64{}
 | 
				
			||||||
 | 
						err = json.Unmarshal(data, &m)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if m != nil && len(m) > 0 {
 | 
				
			||||||
 | 
							this.provinceMap = m
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 更新国家信息
 | 
				
			||||||
 | 
					func (this *ProvinceManager) loop() error {
 | 
				
			||||||
 | 
						rpcClient, err := rpc.SharedRPC()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						resp, err := rpcClient.RegionProvinceRPC().FindAllEnabledRegionProvincesWithCountryId(rpcClient.Context(), &pb.FindAllEnabledRegionProvincesWithCountryIdRequest{
 | 
				
			||||||
 | 
							CountryId: ChinaCountryId,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m := map[string]int64{}
 | 
				
			||||||
 | 
						for _, province := range resp.Provinces {
 | 
				
			||||||
 | 
							for _, code := range province.Codes {
 | 
				
			||||||
 | 
								m[code] = province.Id
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 检查是否有更新
 | 
				
			||||||
 | 
						data, err := json.Marshal(m)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						hash := md5.New()
 | 
				
			||||||
 | 
						hash.Write(data)
 | 
				
			||||||
 | 
						dataHash := fmt.Sprintf("%x", hash.Sum(nil))
 | 
				
			||||||
 | 
						if this.dataHash == dataHash {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						this.dataHash = dataHash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this.locker.Lock()
 | 
				
			||||||
 | 
						this.provinceMap = m
 | 
				
			||||||
 | 
						this.locker.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 保存到本地缓存
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = ioutil.WriteFile(this.cacheFile, data, 0666)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										57
									
								
								internal/iplibrary/manager_province_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								internal/iplibrary/manager_province_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"runtime"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestProvinceManager_load(t *testing.T) {
 | 
				
			||||||
 | 
						manager := NewProvinceManager()
 | 
				
			||||||
 | 
						err := manager.load()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.Log("ok", manager.provinceMap)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestProvinceManager_loop(t *testing.T) {
 | 
				
			||||||
 | 
						manager := NewProvinceManager()
 | 
				
			||||||
 | 
						err := manager.loop()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.Log("ok", manager.provinceMap)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestProvinceManager_loop_skip(t *testing.T) {
 | 
				
			||||||
 | 
						manager := NewProvinceManager()
 | 
				
			||||||
 | 
						for i := 0; i < 10; i++ {
 | 
				
			||||||
 | 
							err := manager.loop()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatal(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestProvinceManager_Lookup(t *testing.T) {
 | 
				
			||||||
 | 
						manager := NewProvinceManager()
 | 
				
			||||||
 | 
						err := manager.load()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.Log(manager.Lookup("安徽省"), manager.Lookup("北京市"))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func BenchmarkProvinceManager_Lookup(b *testing.B) {
 | 
				
			||||||
 | 
						runtime.GOMAXPROCS(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						manager := NewProvinceManager()
 | 
				
			||||||
 | 
						err := manager.load()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							b.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < b.N; i++ {
 | 
				
			||||||
 | 
							_ = manager.Lookup("安徽省")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								internal/iplibrary/manager_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								internal/iplibrary/manager_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						_ "github.com/iwind/TeaGo/bootstrap"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/dbs"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestManager_Load(t *testing.T) {
 | 
				
			||||||
 | 
						dbs.NotifyReady()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						manager := NewManager()
 | 
				
			||||||
 | 
						lib, err := manager.Load()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.Log(lib.Lookup("1.2.3.4"))
 | 
				
			||||||
 | 
						t.Log(lib.Lookup("2.3.4.5"))
 | 
				
			||||||
 | 
						t.Log(lib.Lookup("200.200.200.200"))
 | 
				
			||||||
 | 
						t.Log(lib.Lookup("202.106.0.20"))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNewManager(t *testing.T) {
 | 
				
			||||||
 | 
						dbs.NotifyReady()
 | 
				
			||||||
 | 
						t.Log(SharedLibrary)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										10
									
								
								internal/iplibrary/result.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								internal/iplibrary/result.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Result struct {
 | 
				
			||||||
 | 
						CityId   int64
 | 
				
			||||||
 | 
						Country  string
 | 
				
			||||||
 | 
						Region   string
 | 
				
			||||||
 | 
						Province string
 | 
				
			||||||
 | 
						City     string
 | 
				
			||||||
 | 
						ISP      string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										141
									
								
								internal/iplibrary/updater.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								internal/iplibrary/updater.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,141 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/errors"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/events"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/rpc"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/Tea"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/logs"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						events.On(events.EventStart, func() {
 | 
				
			||||||
 | 
							updater := NewUpdater()
 | 
				
			||||||
 | 
							updater.Start()
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IP库更新程序
 | 
				
			||||||
 | 
					type Updater struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 获取新对象
 | 
				
			||||||
 | 
					func NewUpdater() *Updater {
 | 
				
			||||||
 | 
						return &Updater{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 开始更新
 | 
				
			||||||
 | 
					func (this *Updater) Start() {
 | 
				
			||||||
 | 
						// 这里不需要太频繁检查更新,因为通常不需要更新IP库
 | 
				
			||||||
 | 
						ticker := time.NewTicker(1 * time.Hour)
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							for range ticker.C {
 | 
				
			||||||
 | 
								err := this.loop()
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									logs.Println("[IP_LIBRARY]" + err.Error())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 单次任务
 | 
				
			||||||
 | 
					func (this *Updater) loop() error {
 | 
				
			||||||
 | 
						nodeConfig, err := nodeconfigs.SharedNodeConfig()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if nodeConfig.GlobalConfig == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						code := nodeConfig.GlobalConfig.IPLibrary.Code
 | 
				
			||||||
 | 
						if len(code) == 0 {
 | 
				
			||||||
 | 
							code = serverconfigs.DefaultIPLibraryType
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rpcClient, err := rpc.SharedRPC()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						libraryResp, err := rpcClient.IPLibraryRPC().FindLatestIPLibraryWithType(rpcClient.Context(), &pb.FindLatestIPLibraryWithTypeRequest{Type: code})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						lib := libraryResp.IpLibrary
 | 
				
			||||||
 | 
						if lib == nil || lib.File == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						typeInfo := serverconfigs.FindIPLibraryWithType(code)
 | 
				
			||||||
 | 
						if typeInfo == nil {
 | 
				
			||||||
 | 
							return errors.New("invalid ip library code '" + code + "'")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						path := Tea.Root + "/resources/ipdata/" + code + "/" + code + "." + fmt.Sprintf("%d", lib.CreatedAt) + typeInfo.GetString("ext")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 是否已经存在
 | 
				
			||||||
 | 
						_, err = os.Stat(path)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 开始下载
 | 
				
			||||||
 | 
						fileChunkIdsResp, err := rpcClient.FileChunkRPC().FindAllFileChunkIds(rpcClient.Context(), &pb.FindAllFileChunkIdsRequest{FileId: lib.File.Id})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						chunkIds := fileChunkIdsResp.FileChunkIds
 | 
				
			||||||
 | 
						if len(chunkIds) == 0 {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						isOk := false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fp, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0666)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							// 如果保存不成功就直接删除
 | 
				
			||||||
 | 
							if !isOk {
 | 
				
			||||||
 | 
								_ = fp.Close()
 | 
				
			||||||
 | 
								_ = os.Remove(path)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						for _, chunkId := range chunkIds {
 | 
				
			||||||
 | 
							chunkResp, err := rpcClient.FileChunkRPC().DownloadFileChunk(rpcClient.Context(), &pb.DownloadFileChunkRequest{FileChunkId: chunkId})
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							chunk := chunkResp.FileChunk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if chunk == nil {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							_, err = fp.Write(chunk.Data)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = fp.Close()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 重新加载
 | 
				
			||||||
 | 
						library, err := SharedManager.Load()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						SharedLibrary = library
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						isOk = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								internal/iplibrary/updater_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								internal/iplibrary/updater_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					package iplibrary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						_ "github.com/iwind/TeaGo/bootstrap"
 | 
				
			||||||
 | 
						"github.com/iwind/TeaGo/dbs"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestUpdater_loop(t *testing.T) {
 | 
				
			||||||
 | 
						dbs.NotifyReady()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						updater := NewUpdater()
 | 
				
			||||||
 | 
						err := updater.loop()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						t.Log("ok")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,22 +1,85 @@
 | 
				
			|||||||
package nodes
 | 
					package nodes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/iplibrary"
 | 
				
			||||||
 | 
						"github.com/TeaOSLab/EdgeNode/internal/logs"
 | 
				
			||||||
	"github.com/TeaOSLab/EdgeNode/internal/waf"
 | 
						"github.com/TeaOSLab/EdgeNode/internal/waf"
 | 
				
			||||||
	"github.com/iwind/TeaGo/logs"
 | 
						"github.com/iwind/TeaGo/lists"
 | 
				
			||||||
	"github.com/iwind/TeaGo/types"
 | 
						"github.com/iwind/TeaGo/types"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 调用WAF
 | 
					// 调用WAF
 | 
				
			||||||
func (this *HTTPRequest) doWAFRequest() (blocked bool) {
 | 
					func (this *HTTPRequest) doWAFRequest() (blocked bool) {
 | 
				
			||||||
 | 
						// 检查配置是否为空
 | 
				
			||||||
 | 
						if this.web.FirewallPolicy == nil || this.web.FirewallPolicy.Inbound == nil || !this.web.FirewallPolicy.Inbound.IsOn {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 检查IP白名单
 | 
				
			||||||
 | 
						remoteAddr := this.requestRemoteAddr()
 | 
				
			||||||
 | 
						inbound := this.web.FirewallPolicy.Inbound
 | 
				
			||||||
 | 
						if inbound.WhiteListRef != nil && inbound.WhiteListRef.IsOn && inbound.WhiteListRef.ListId > 0 {
 | 
				
			||||||
 | 
							list := iplibrary.SharedIPListManager.FindList(inbound.WhiteListRef.ListId)
 | 
				
			||||||
 | 
							if list != nil && list.Contains(iplibrary.IP2Long(remoteAddr)) {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 检查IP黑名单
 | 
				
			||||||
 | 
						if inbound.BlackListRef != nil && inbound.BlackListRef.IsOn && inbound.BlackListRef.ListId > 0 {
 | 
				
			||||||
 | 
							list := iplibrary.SharedIPListManager.FindList(inbound.BlackListRef.ListId)
 | 
				
			||||||
 | 
							if list != nil && list.Contains(iplibrary.IP2Long(remoteAddr)) {
 | 
				
			||||||
 | 
								// TODO 可以配置对封禁的处理方式等
 | 
				
			||||||
 | 
								this.writer.WriteHeader(http.StatusForbidden)
 | 
				
			||||||
 | 
								this.writer.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 检查地区封禁
 | 
				
			||||||
 | 
						if iplibrary.SharedLibrary != nil {
 | 
				
			||||||
 | 
							if this.web.FirewallPolicy.Inbound.Region != nil && this.web.FirewallPolicy.Inbound.Region.IsOn {
 | 
				
			||||||
 | 
								regionConfig := this.web.FirewallPolicy.Inbound.Region
 | 
				
			||||||
 | 
								if regionConfig.IsNotEmpty() {
 | 
				
			||||||
 | 
									result, err := iplibrary.SharedLibrary.Lookup(remoteAddr)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										logs.Error("REQUEST", "iplibrary lookup failed: "+err.Error())
 | 
				
			||||||
 | 
									} else if result != nil {
 | 
				
			||||||
 | 
										// 检查国家级别封禁
 | 
				
			||||||
 | 
										if len(regionConfig.DenyCountryIds) > 0 && len(result.Country) > 0 {
 | 
				
			||||||
 | 
											countryId := iplibrary.SharedCountryManager.Lookup(result.Country)
 | 
				
			||||||
 | 
											if countryId > 0 && lists.ContainsInt64(regionConfig.DenyCountryIds, countryId) {
 | 
				
			||||||
 | 
												// TODO 可以配置对封禁的处理方式等
 | 
				
			||||||
 | 
												this.writer.WriteHeader(http.StatusForbidden)
 | 
				
			||||||
 | 
												this.writer.Close()
 | 
				
			||||||
 | 
												return true
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// 检查省份封禁
 | 
				
			||||||
 | 
										if len(regionConfig.DenyProvinceIds) > 0 && len(result.Province) > 0 {
 | 
				
			||||||
 | 
											provinceId := iplibrary.SharedProvinceManager.Lookup(result.Province)
 | 
				
			||||||
 | 
											if provinceId > 0 && lists.ContainsInt64(regionConfig.DenyProvinceIds, provinceId) {
 | 
				
			||||||
 | 
												// TODO 可以配置对封禁的处理方式等
 | 
				
			||||||
 | 
												this.writer.WriteHeader(http.StatusForbidden)
 | 
				
			||||||
 | 
												this.writer.Close()
 | 
				
			||||||
 | 
												return true
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	w := sharedWAFManager.FindWAF(this.web.FirewallPolicy.Id)
 | 
						w := sharedWAFManager.FindWAF(this.web.FirewallPolicy.Id)
 | 
				
			||||||
	if w == nil {
 | 
						if w == nil {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	goNext, ruleGroup, ruleSet, err := w.MatchRequest(this.RawReq, this.writer)
 | 
						goNext, ruleGroup, ruleSet, err := w.MatchRequest(this.RawReq, this.writer)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logs.Error(err)
 | 
							logs.Error("REQUEST", this.rawURI+": "+err.Error())
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -42,7 +105,7 @@ func (this *HTTPRequest) doWAFResponse(resp *http.Response) (blocked bool) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	goNext, ruleGroup, ruleSet, err := w.MatchResponse(this.RawReq, resp, this.writer)
 | 
						goNext, ruleGroup, ruleSet, err := w.MatchResponse(this.RawReq, resp, this.writer)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		logs.Error(err)
 | 
							logs.Error("REQUEST", this.rawURI+": "+err.Error())
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,6 +53,9 @@ func (this *Node) Test() error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// 启动
 | 
					// 启动
 | 
				
			||||||
func (this *Node) Start() {
 | 
					func (this *Node) Start() {
 | 
				
			||||||
 | 
						// 启动事件
 | 
				
			||||||
 | 
						events.Notify(events.EventStart)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 处理信号
 | 
						// 处理信号
 | 
				
			||||||
	this.listenSignals()
 | 
						this.listenSignals()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,6 +61,34 @@ func (this *RPCClient) APINodeRPC() pb.APINodeServiceClient {
 | 
				
			|||||||
	return pb.NewAPINodeServiceClient(this.pickConn())
 | 
						return pb.NewAPINodeServiceClient(this.pickConn())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *RPCClient) IPLibraryRPC() pb.IPLibraryServiceClient {
 | 
				
			||||||
 | 
						return pb.NewIPLibraryServiceClient(this.pickConn())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *RPCClient) RegionCountryRPC() pb.RegionCountryServiceClient {
 | 
				
			||||||
 | 
						return pb.NewRegionCountryServiceClient(this.pickConn())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *RPCClient) RegionProvinceRPC() pb.RegionProvinceServiceClient {
 | 
				
			||||||
 | 
						return pb.NewRegionProvinceServiceClient(this.pickConn())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *RPCClient) IPListRPC() pb.IPListServiceClient {
 | 
				
			||||||
 | 
						return pb.NewIPListServiceClient(this.pickConn())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *RPCClient) IPItemRPC() pb.IPItemServiceClient {
 | 
				
			||||||
 | 
						return pb.NewIPItemServiceClient(this.pickConn())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *RPCClient) FileRPC() pb.FileServiceClient {
 | 
				
			||||||
 | 
						return pb.NewFileServiceClient(this.pickConn())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (this *RPCClient) FileChunkRPC() pb.FileChunkServiceClient {
 | 
				
			||||||
 | 
						return pb.NewFileChunkServiceClient(this.pickConn())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 节点上下文信息
 | 
					// 节点上下文信息
 | 
				
			||||||
func (this *RPCClient) Context() context.Context {
 | 
					func (this *RPCClient) Context() context.Context {
 | 
				
			||||||
	ctx := context.Background()
 | 
						ctx := context.Background()
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user