mirror of
				https://github.com/TeaOSLab/EdgeNode.git
				synced 2025-11-04 16:00:25 +08:00 
			
		
		
		
	支持设置HTTP防火墙
This commit is contained in:
		@@ -6,6 +6,7 @@ import (
 | 
			
		||||
	teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeNode/internal/events"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
 | 
			
		||||
	"os"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
@@ -35,6 +36,16 @@ func Firewall() FirewallInterface {
 | 
			
		||||
		return currentFirewall
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// http firewall
 | 
			
		||||
	{
 | 
			
		||||
		endpoint, _ := os.LookupEnv("EDGE_HTTP_FIREWALL_ENDPOINT")
 | 
			
		||||
		if len(endpoint) > 0 {
 | 
			
		||||
			var httpFirewall = NewHTTPFirewall(endpoint)
 | 
			
		||||
			currentFirewall = httpFirewall
 | 
			
		||||
			return httpFirewall
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// nftables
 | 
			
		||||
	if runtime.GOOS == "linux" {
 | 
			
		||||
		nftables, err := NewNFTablesFirewall()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										150
									
								
								internal/firewalls/firewall_http.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								internal/firewalls/firewall_http.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,150 @@
 | 
			
		||||
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
			
		||||
 | 
			
		||||
package firewalls
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
	"github.com/iwind/TeaGo/types"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type HTTPFirewall struct {
 | 
			
		||||
	client   *http.Client
 | 
			
		||||
	endpoint string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewHTTPFirewall(endpoint string) *HTTPFirewall {
 | 
			
		||||
	return &HTTPFirewall{
 | 
			
		||||
		client:   http.DefaultClient,
 | 
			
		||||
		endpoint: endpoint,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Name 名称
 | 
			
		||||
func (this *HTTPFirewall) Name() string {
 | 
			
		||||
	result, err := this.get("/name", nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	return result.GetString("name")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsReady 是否已准备被调用
 | 
			
		||||
func (this *HTTPFirewall) IsReady() bool {
 | 
			
		||||
	result, err := this.get("/isReady", nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return result.GetBool("result")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsMock 是否为模拟
 | 
			
		||||
func (this *HTTPFirewall) IsMock() bool {
 | 
			
		||||
	result, err := this.get("/isMock", nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return result.GetBool("result")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AllowPort 允许端口
 | 
			
		||||
func (this *HTTPFirewall) AllowPort(port int, protocol string) error {
 | 
			
		||||
	_, err := this.get("/allowPort", map[string]string{
 | 
			
		||||
		"port":     types.String(port),
 | 
			
		||||
		"protocol": protocol,
 | 
			
		||||
	})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemovePort 删除端口
 | 
			
		||||
func (this *HTTPFirewall) RemovePort(port int, protocol string) error {
 | 
			
		||||
	_, err := this.get("/removePort", map[string]string{
 | 
			
		||||
		"port":     types.String(port),
 | 
			
		||||
		"protocol": protocol,
 | 
			
		||||
	})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RejectSourceIP 拒绝某个源IP连接
 | 
			
		||||
func (this *HTTPFirewall) RejectSourceIP(ip string, timeoutSeconds int) error {
 | 
			
		||||
	_, err := this.get("/rejectSourceIP", map[string]string{
 | 
			
		||||
		"ip":             ip,
 | 
			
		||||
		"timeoutSeconds": types.String(timeoutSeconds),
 | 
			
		||||
	})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DropSourceIP 丢弃某个源IP数据
 | 
			
		||||
// ip 要封禁的IP
 | 
			
		||||
// timeoutSeconds 过期时间
 | 
			
		||||
// async 是否异步
 | 
			
		||||
func (this *HTTPFirewall) DropSourceIP(ip string, timeoutSeconds int, async bool) error {
 | 
			
		||||
	var asyncString = "false"
 | 
			
		||||
	if async {
 | 
			
		||||
		asyncString = "true"
 | 
			
		||||
	}
 | 
			
		||||
	_, err := this.get("/dropSourceIP", map[string]string{
 | 
			
		||||
		"ip":             ip,
 | 
			
		||||
		"timeoutSeconds": types.String(timeoutSeconds),
 | 
			
		||||
		"async":          asyncString,
 | 
			
		||||
	})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RemoveSourceIP 删除某个源IP
 | 
			
		||||
func (this *HTTPFirewall) RemoveSourceIP(ip string) error {
 | 
			
		||||
	_, err := this.get("/removeSourceIP", map[string]string{
 | 
			
		||||
		"ip": ip,
 | 
			
		||||
	})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *HTTPFirewall) get(path string, args map[string]string) (result maps.Map, err error) {
 | 
			
		||||
	var urlString = this.endpoint + path
 | 
			
		||||
	if len(args) > 0 {
 | 
			
		||||
		var query = &url.Values{}
 | 
			
		||||
		for k, v := range args {
 | 
			
		||||
			query.Add(k, v)
 | 
			
		||||
		}
 | 
			
		||||
		urlString += "?" + query.Encode()
 | 
			
		||||
	}
 | 
			
		||||
	req, err := http.NewRequest(http.MethodGet, urlString, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp, err := this.client.Do(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if resp.StatusCode != http.StatusOK {
 | 
			
		||||
		return nil, errors.New("server response code '" + types.String(resp.StatusCode) + "'")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer func() {
 | 
			
		||||
		_ = resp.Body.Close()
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	data, err := io.ReadAll(resp.Body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("read response failed: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(data) == 0 {
 | 
			
		||||
		return maps.Map{}, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	result = maps.Map{}
 | 
			
		||||
	err = json.Unmarshal(data, &result)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("decode response failed: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user