feat: grpc / web get real ip
This commit is contained in:
		
							parent
							
								
									cde2ef3bd7
								
							
						
					
					
						commit
						d699d0ee87
					
				@ -5,6 +5,7 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
						"net/netip"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
@ -21,7 +22,6 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ServeWeb() http.Handler {
 | 
					func ServeWeb() http.Handler {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	gin.SetMode(gin.ReleaseMode)
 | 
						gin.SetMode(gin.ReleaseMode)
 | 
				
			||||||
	r := gin.Default()
 | 
						r := gin.Default()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -34,12 +34,39 @@ func ServeWeb() http.Handler {
 | 
				
			|||||||
		r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))
 | 
							r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r.Use(realIp)
 | 
				
			||||||
	r.Use(recordPath)
 | 
						r.Use(recordPath)
 | 
				
			||||||
	routers(r)
 | 
						routers(r)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return r
 | 
						return r
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func realIp(c *gin.Context) {
 | 
				
			||||||
 | 
						if singleton.Conf.RealIPHeader == "" {
 | 
				
			||||||
 | 
							c.Next()
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if singleton.Conf.RealIPHeader == model.ConfigUsePeerIP {
 | 
				
			||||||
 | 
							c.Set(model.CtxKeyRealIPStr, c.RemoteIP())
 | 
				
			||||||
 | 
							c.Next()
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vals := c.Request.Header.Get(singleton.Conf.RealIPHeader)
 | 
				
			||||||
 | 
						if vals == "" {
 | 
				
			||||||
 | 
							c.AbortWithStatusJSON(http.StatusOK, model.CommonResponse[any]{Success: false, Error: "real ip header not found"})
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ip, err := netip.ParseAddr(vals)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							c.AbortWithStatusJSON(http.StatusOK, model.CommonResponse[any]{Success: false, Error: err.Error()})
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.Set(model.CtxKeyRealIPStr, ip.String())
 | 
				
			||||||
 | 
						c.Next()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func routers(r *gin.Engine) {
 | 
					func routers(r *gin.Engine) {
 | 
				
			||||||
	authMiddleware, err := jwt.New(initParams())
 | 
						authMiddleware, err := jwt.New(initParams())
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -127,6 +154,7 @@ func routers(r *gin.Engine) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func recordPath(c *gin.Context) {
 | 
					func recordPath(c *gin.Context) {
 | 
				
			||||||
 | 
						log.Printf("bingo web real ip: %s", c.GetString(model.CtxKeyRealIPStr))
 | 
				
			||||||
	url := c.Request.URL.String()
 | 
						url := c.Request.URL.String()
 | 
				
			||||||
	for _, p := range c.Params {
 | 
						for _, p := range c.Params {
 | 
				
			||||||
		url = strings.Replace(url, p.Value, ":"+p.Key, 1)
 | 
							url = strings.Replace(url, p.Value, ":"+p.Key, 1)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +1,15 @@
 | 
				
			|||||||
package rpc
 | 
					package rpc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
						"net/netip"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"google.golang.org/grpc"
 | 
						"google.golang.org/grpc"
 | 
				
			||||||
 | 
						"google.golang.org/grpc/metadata"
 | 
				
			||||||
 | 
						"google.golang.org/grpc/peer"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/hashicorp/go-uuid"
 | 
						"github.com/hashicorp/go-uuid"
 | 
				
			||||||
	"github.com/naiba/nezha/model"
 | 
						"github.com/naiba/nezha/model"
 | 
				
			||||||
@ -16,12 +20,42 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ServeRPC() *grpc.Server {
 | 
					func ServeRPC() *grpc.Server {
 | 
				
			||||||
	server := grpc.NewServer()
 | 
						server := grpc.NewServer(grpc.UnaryInterceptor(getRealIp))
 | 
				
			||||||
	rpcService.NezhaHandlerSingleton = rpcService.NewNezhaHandler()
 | 
						rpcService.NezhaHandlerSingleton = rpcService.NewNezhaHandler()
 | 
				
			||||||
	proto.RegisterNezhaServiceServer(server, rpcService.NezhaHandlerSingleton)
 | 
						proto.RegisterNezhaServiceServer(server, rpcService.NezhaHandlerSingleton)
 | 
				
			||||||
	return server
 | 
						return server
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getRealIp(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
 | 
				
			||||||
 | 
						if singleton.Conf.RealIPHeader == "" {
 | 
				
			||||||
 | 
							return handler(ctx, req)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if singleton.Conf.RealIPHeader == model.ConfigUsePeerIP {
 | 
				
			||||||
 | 
							p, ok := peer.FromContext(ctx)
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								return nil, fmt.Errorf("peer not found")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							addrPort, err := netip.ParseAddrPort(p.Addr.String())
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx = context.WithValue(ctx, model.CtxKeyRealIP{}, addrPort.Addr().String())
 | 
				
			||||||
 | 
							return handler(ctx, req)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vals := metadata.ValueFromIncomingContext(ctx, singleton.Conf.RealIPHeader)
 | 
				
			||||||
 | 
						if len(vals) == 0 {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("real ip header not found")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ip, err := netip.ParseAddr(vals[0])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ctx = context.WithValue(ctx, model.CtxKeyRealIP{}, ip.String())
 | 
				
			||||||
 | 
						return handler(ctx, req)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func DispatchTask(serviceSentinelDispatchBus <-chan model.Service) {
 | 
					func DispatchTask(serviceSentinelDispatchBus <-chan model.Service) {
 | 
				
			||||||
	workedServerIndex := 0
 | 
						workedServerIndex := 0
 | 
				
			||||||
	for task := range serviceSentinelDispatchBus {
 | 
						for task := range serviceSentinelDispatchBus {
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,12 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const CtxKeyAuthorizedUser = "ckau"
 | 
					const (
 | 
				
			||||||
 | 
						CtxKeyAuthorizedUser = "ckau"
 | 
				
			||||||
 | 
						CtxKeyRealIPStr      = "ckri"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CtxKeyRealIP struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Common struct {
 | 
					type Common struct {
 | 
				
			||||||
	ID        uint64    `gorm:"primaryKey" json:"id,omitempty"`
 | 
						ID        uint64    `gorm:"primaryKey" json:"id,omitempty"`
 | 
				
			||||||
 | 
				
			|||||||
@ -11,12 +11,14 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	ConfigCoverAll = iota
 | 
						ConfigUsePeerIP = "NZ::Use-Peer-IP"
 | 
				
			||||||
 | 
						ConfigCoverAll  = iota
 | 
				
			||||||
	ConfigCoverIgnoreAll
 | 
						ConfigCoverIgnoreAll
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Config struct {
 | 
					type Config struct {
 | 
				
			||||||
	Debug bool `mapstructure:"debug" json:"debug,omitempty"` // debug模式开关
 | 
						Debug        bool   `mapstructure:"debug" json:"debug,omitempty"`                   // debug模式开关
 | 
				
			||||||
 | 
						RealIPHeader string `mapstructure:"real_ip_header" json:"real_ip_header,omitempty"` // 真实IP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Language       string `mapstructure:"language" json:"language"` // 系统语言,默认 zh_CN
 | 
						Language       string `mapstructure:"language" json:"language"` // 系统语言,默认 zh_CN
 | 
				
			||||||
	SiteName       string `mapstructure:"site_name" json:"site_name"`
 | 
						SiteName       string `mapstructure:"site_name" json:"site_name"`
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@ package rpc
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"google.golang.org/grpc/codes"
 | 
						"google.golang.org/grpc/codes"
 | 
				
			||||||
@ -24,6 +25,9 @@ func (a *authHandler) Check(ctx context.Context) (uint64, error) {
 | 
				
			|||||||
		return 0, status.Errorf(codes.Unauthenticated, "获取 metaData 失败")
 | 
							return 0, status.Errorf(codes.Unauthenticated, "获取 metaData 失败")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						realIp := ctx.Value(model.CtxKeyRealIP{})
 | 
				
			||||||
 | 
						log.Printf("bingo rpc realIp: %s, metadata: %v", realIp, md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var clientSecret string
 | 
						var clientSecret string
 | 
				
			||||||
	if value, ok := md["client_secret"]; ok {
 | 
						if value, ok := md["client_secret"]; ok {
 | 
				
			||||||
		clientSecret = value[0]
 | 
							clientSecret = value[0]
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user