diff --git a/cmd/goxy/main.go b/cmd/goxy/main.go index bb50b0d..8e34e78 100644 --- a/cmd/goxy/main.go +++ b/cmd/goxy/main.go @@ -2,18 +2,23 @@ package main import ( "context" + "net/http" + "os" + "os/signal" + "syscall" + "time" + "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" "github.com/spf13/pflag" "github.com/spf13/viper" + "google.golang.org/grpc" + "goxy/internal/common" + "goxy/internal/export" + "goxy/internal/grpcauth" "goxy/internal/proxy" "goxy/internal/web" - "net/http" - "os" - "os/signal" - "syscall" - "time" ) var ( @@ -31,7 +36,8 @@ func main() { parseConfig() cfg := parseProxyConfig() - m := runProxyManager(cfg) + producer := createMongolProducer(cfg) + m := runProxyManager(cfg, producer) s := web.NewServer(m) httpServer := startHttpServer(s) @@ -87,6 +93,30 @@ func parseConfig() { } } +func createMongolConnection(addr, token string) *grpc.ClientConn { + var opts []grpc.DialOption + opts = append(opts, grpc.WithInsecure()) + if token != "" { + interceptor := grpcauth.NewClientInterceptor(token) + opts = append(opts, grpc.WithUnaryInterceptor(interceptor.Unary())) + opts = append(opts, grpc.WithStreamInterceptor(interceptor.Stream())) + } + conn, err := grpc.Dial(addr, opts...) + if err != nil { + logrus.Fatalf("dialing grpc: %v", err) + } + return conn +} + +func createMongolProducer(cfg *common.ProxyConfig) *export.ProducerClient { + if cfg.Mongol == nil { + logrus.Info("Mongol exporter is disabled") + return nil + } + conn := createMongolConnection(cfg.Mongol.Addr, cfg.Mongol.Token) + return export.NewProducerClient(conn) +} + func parseProxyConfig() *common.ProxyConfig { cfg := new(common.ProxyConfig) if err := viper.Unmarshal(&cfg); err != nil { @@ -95,8 +125,8 @@ func parseProxyConfig() *common.ProxyConfig { return cfg } -func runProxyManager(cfg *common.ProxyConfig) *proxy.Manager { - m, err := proxy.NewManager(cfg) +func runProxyManager(cfg *common.ProxyConfig, producer *export.ProducerClient) *proxy.Manager { + m, err := proxy.NewManager(cfg, producer) if err != nil { logrus.Fatalf("Error creating proxy manager: %v", err) } diff --git a/config.yml b/config.yml index b93b38a..dc51d7d 100644 --- a/config.yml +++ b/config.yml @@ -1,59 +1,59 @@ rules: ####### TCP RULES ######## - name: regex_kek - type: tcp::regex + type: regex args: - "ke?k" - name: contains_attack - type: tcp::contains + type: contains args: - "attack" - name: ingress_not_contains_legit - type: tcp::ingress::not::contains + type: ingress::not::contains args: - "legit" - - name: volgactf_flag - type: tcp::volgactf_flag - args: - - "JCPOmYvE0bRQ4t6B-yu7cz3dp8F1IVWeXgn5AwkZfqa9_UxDThjKNiMlSL2GHosr." + # - name: volgactf_flag + # type: volgactf_flag + # args: + # - "JCPOmYvE0bRQ4t6B-yu7cz3dp8F1IVWeXgn5AwkZfqa9_UxDThjKNiMlSL2GHosr." ######## END TCP RULES ######### ######## HTTP RULES ######### - name: http_form_username_contains_admin - type: http::form::array::any::contains + type: form::any::contains field: username args: - "admi" - name: http_body_contains_pt - type: http::ingress::body::contains + type: ingress::body::contains args: - "../" - name: curl_request - type: http::headers::any::icontains + type: headers::any::icontains field: "User-Agent" args: - "cUrl" - name: requests - type: http::headers::any::contains + type: headers::any::contains field: "User-Agent" args: - "python-requests" - name: not_requests_2184 - type: http::ingress::not::headers::contains + type: ingress::not::headers::contains field: "User-Agent" args: - "python-requests/2.18.4" - - name: "http_volgactf" - type: http::transform_volga + # - name: "http_volgactf" + # type: transform_volga ######## END HTTP RULES ######### services: @@ -62,8 +62,8 @@ services: listen: 0.0.0.0:1337 target: 127.0.0.1:1338 filters: - - rule: volgactf_flag - verdict: "alert::flag transformed" + # - rule: volgactf_flag + # verdict: "alert::flag transformed" - rule: regex_kek verdict: inc::keks - rule: egress @@ -91,9 +91,12 @@ services: verdict: "alert::requests" - rule: not_requests_2184 verdict: "alert::not requests 2.18.4" - - rule: http_volgactf - verdict: "alert::flag transformed" +# - rule: http_volgactf +# verdict: "alert::flag transformed" web: username: admin password: 1234 + +mongol: + addr: 127.0.0.1:5139 diff --git a/go.mod b/go.mod index b0178c7..d596e5a 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,11 @@ require ( github.com/gin-contrib/cors v1.3.1 github.com/gin-contrib/gzip v0.0.3 github.com/gin-gonic/gin v1.6.3 + github.com/google/uuid v1.1.2 github.com/sirupsen/logrus v1.7.0 github.com/spf13/pflag v1.0.3 github.com/spf13/viper v1.7.1 go.uber.org/atomic v1.4.0 + google.golang.org/grpc v1.42.0 + google.golang.org/protobuf v1.27.1 ) diff --git a/go.sum b/go.sum index 183f594..33738d5 100644 --- a/go.sum +++ b/go.sum @@ -17,6 +17,7 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -24,8 +25,16 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -36,6 +45,12 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -74,17 +89,33 @@ github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFU github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= @@ -93,6 +124,7 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -172,12 +204,14 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= @@ -204,8 +238,10 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -217,6 +253,7 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -226,6 +263,7 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -258,9 +296,12 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -281,8 +322,9 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= @@ -299,6 +341,7 @@ golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -307,6 +350,9 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -325,9 +371,31 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= @@ -341,11 +409,15 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/internal/common/config.go b/internal/common/config.go index b48f8cc..20cbba7 100644 --- a/internal/common/config.go +++ b/internal/common/config.go @@ -24,7 +24,13 @@ type ServiceConfig struct { Filters []FilterConfig `json:"filters" mapstructure:"filters"` } +type MongolConfig struct { + Addr string `mapstructure:"addr"` + Token string `mapstructure:"token"` +} + type ProxyConfig struct { Rules []RuleConfig `json:"rules" mapstructure:"rules"` Services []ServiceConfig `json:"services" mapstructure:"services"` + Mongol *MongolConfig `json:"-" mapstructure:"mongol"` } diff --git a/internal/export/client.go b/internal/export/client.go new file mode 100644 index 0000000..d5b8f2f --- /dev/null +++ b/internal/export/client.go @@ -0,0 +1,44 @@ +package export + +import ( + "context" + "fmt" + + "google.golang.org/grpc" + + mgpb "goxy/lib/mongol" +) + +func NewProducerClient(cc grpc.ClientConnInterface) *ProducerClient { + return &ProducerClient{c: mgpb.NewMonGolClient(cc)} +} + +type ProducerClient struct { + c mgpb.MonGolClient +} + +func (c *ProducerClient) Send(ctx context.Context, p *Packet) error { + req := mgpb.AddPacketRequest{Packet: p.ToProto()} + _, err := c.c.AddPacket(ctx, &req) + if err != nil { + return fmt.Errorf("making AddPacket request: %w", err) + } + return nil +} + +func (c *ProducerClient) AddFilters(ctx context.Context, filters []string) ([]*mgpb.Filter, error) { + req := mgpb.RegisterFiltersRequest{Names: filters} + resp, err := c.c.RegisterFilters(ctx, &req) + if err != nil { + return nil, fmt.Errorf("making RegisterFilters request: %w", err) + } + return resp.GetFilters(), nil +} + +func (c *ProducerClient) GetConfig(ctx context.Context) (*mgpb.Config, error) { + resp, err := c.c.GetConfig(ctx, &mgpb.GetConfigRequest{}) + if err != nil { + return nil, fmt.Errorf("making GetConfig request: %w", err) + } + return resp.GetConfig(), nil +} diff --git a/internal/export/endpoints.go b/internal/export/endpoints.go new file mode 100644 index 0000000..b5a4b41 --- /dev/null +++ b/internal/export/endpoints.go @@ -0,0 +1,44 @@ +package export + +import ( + "fmt" + + mgpb "goxy/lib/mongol" +) + +// EndpointData stores packet endpoints in plain format. +type EndpointData struct { + IPSrc string + IPDst string + PortSrc int + PortDst int +} + +func (e *EndpointData) String() string { + return fmt.Sprintf("%s:%d->%s:%d", e.IPSrc, e.PortSrc, e.IPDst, e.PortDst) +} + +// Reversed returns EndpointData with swapped source and destination. +func (e *EndpointData) Reversed() *EndpointData { + res := &EndpointData{ + IPSrc: e.IPDst, + IPDst: e.IPSrc, + PortSrc: e.PortDst, + PortDst: e.PortSrc, + } + return res +} + +// ReversedString returns a string representation of reversed endpoints (no need to allocate new structure). +func (e *EndpointData) ReversedString() string { + return fmt.Sprintf("%s:%d->%s:%d", e.IPDst, e.PortDst, e.IPSrc, e.PortSrc) +} + +func (e *EndpointData) ToProto() *mgpb.EndpointData { + return &mgpb.EndpointData{ + IpSrc: e.IPSrc, + IpDst: e.IPDst, + PortSrc: int32(e.PortSrc), + PortDst: int32(e.PortDst), + } +} diff --git a/internal/export/packet.go b/internal/export/packet.go new file mode 100644 index 0000000..6840f19 --- /dev/null +++ b/internal/export/packet.go @@ -0,0 +1,50 @@ +package export + +import ( + "time" + + "google.golang.org/protobuf/types/known/timestamppb" + + mgpb "goxy/lib/mongol" +) + +// BasePacket contains common data shared by stream. +type BasePacket struct { + Source string + Endpoints *EndpointData + Proto string + ProducerStreamID string +} + +// Packet extends BasePacket and adds packet-specific info, so all data in BasePacket is not reallocated. +type Packet struct { + *BasePacket + + Content []byte + CaptureTime time.Time + FilterData uint64 + Inbound bool + Reversed bool +} + +// DumpEndpoints correctly returns packet endpoints (reversing if the packet is reversed). +func (p *Packet) DumpEndpoints() string { + if p.Reversed { + return p.Endpoints.ReversedString() + } + return p.Endpoints.String() +} + +func (p *Packet) ToProto() *mgpb.Packet { + return &mgpb.Packet{ + Source: p.Source, + Inbound: p.Inbound, + Reversed: p.Reversed, + Endpoints: p.Endpoints.ToProto(), + Proto: p.Proto, + Content: p.Content, + CaptureTime: timestamppb.New(p.CaptureTime), + FilterData: p.FilterData, + ProducerStreamId: p.ProducerStreamID, + } +} diff --git a/internal/proxy/http/filters/composite.go b/internal/filters/composite.go similarity index 83% rename from internal/proxy/http/filters/composite.go rename to internal/filters/composite.go index a63e108..d9c8912 100644 --- a/internal/proxy/http/filters/composite.go +++ b/internal/filters/composite.go @@ -2,9 +2,9 @@ package filters import ( "fmt" - "goxy/internal/common" - "goxy/internal/proxy/http/wrapper" "strings" + + "goxy/internal/common" ) func NewCompositeAndRule(rs RuleSet, cfg common.RuleConfig) (Rule, error) { @@ -40,9 +40,9 @@ type CompositeAndRule struct { rules []Rule } -func (r CompositeAndRule) Apply(ctx *common.ProxyContext, e wrapper.Entity) (bool, error) { +func (r CompositeAndRule) Apply(ctx *common.ProxyContext, v interface{}) (bool, error) { for _, rule := range r.rules { - res, err := rule.Apply(ctx, e) + res, err := rule.Apply(ctx, v) if err != nil { return false, fmt.Errorf("error in rule %T: %w", rule, err) } @@ -65,8 +65,8 @@ type CompositeNotRule struct { rule Rule } -func (r CompositeNotRule) Apply(ctx *common.ProxyContext, e wrapper.Entity) (bool, error) { - res, err := r.rule.Apply(ctx, e) +func (r CompositeNotRule) Apply(ctx *common.ProxyContext, v interface{}) (bool, error) { + res, err := r.rule.Apply(ctx, v) if err != nil { return false, fmt.Errorf("error in rule %T: %w", r.rule, err) } diff --git a/internal/proxy/http/filters/default.go b/internal/filters/default.go similarity index 58% rename from internal/proxy/http/filters/default.go rename to internal/filters/default.go index 9644a52..be972c5 100644 --- a/internal/proxy/http/filters/default.go +++ b/internal/filters/default.go @@ -5,19 +5,20 @@ var DefaultRules = map[string]Rule{ "egress": &CompositeNotRule{new(IngressRule)}, } -var DefaultTransformers = map[string]Rule{ - "transform_volga": NewTransformVolgaCTF(), -} - var DefaultRuleWrappers = map[string]RuleWrapperCreator{ "ingress": NewIngressWrapper, "egress": NewEgressWrapper, "not": NewNotWrapper, + "any": NewAnyWrapper, + "field": NewFieldWrapper, } var DefaultRuleCreators = map[string]RuleCreator{ - "and": NewCompositeAndRule, - "not": NewCompositeNotRule, + "and": NewCompositeAndRule, + "not": NewCompositeNotRule, + "contains": NewContainsRule, + "icontains": NewIContainsRule, + "regex": NewRegexRule, } var DefaultEntityConverters = map[string]EntityConverter{ @@ -29,15 +30,3 @@ var DefaultEntityConverters = map[string]EntityConverter{ "form": FormEntityConverter{}, "headers": HeadersEntityConverter{}, } - -var DefaultRawRuleCreators = map[string]RawRuleCreator{ - "contains": NewContainsRawRule, - "icontains": NewIContainsRawRule, - "regex": NewRegexRawRule, -} - -var DefaultRawRuleWrappers = map[string]RawRuleWrapperCreator{ - "any": NewAnyWrapper, - "array": NewArrayWrapper, - "not": NewNotWrapperRaw, -} diff --git a/internal/proxy/http/filters/entities.go b/internal/filters/entities.go similarity index 70% rename from internal/proxy/http/filters/entities.go rename to internal/filters/entities.go index 9792937..d5038f3 100644 --- a/internal/proxy/http/filters/entities.go +++ b/internal/filters/entities.go @@ -2,7 +2,8 @@ package filters import ( "fmt" - "goxy/internal/proxy/http/wrapper" + + "goxy/internal/wrapper" ) type JsonEntityConverter struct{} @@ -22,7 +23,10 @@ func (c JsonEntityConverter) String() string { type CookiesEntityConverter struct{} func (c CookiesEntityConverter) Convert(e wrapper.Entity) (interface{}, error) { - cookies := e.GetCookies() + cookies, err := e.GetCookies() + if err != nil { + return nil, fmt.Errorf("getting cookies: %w", err) + } result := make(map[string]string) for _, cookie := range cookies { result[cookie.Name] = cookie.Value @@ -37,7 +41,11 @@ func (c CookiesEntityConverter) String() string { type HeadersEntityConverter struct{} func (c HeadersEntityConverter) Convert(e wrapper.Entity) (interface{}, error) { - return convertMapListString(e.GetHeaders()), nil + headers, err := e.GetHeaders() + if err != nil { + return nil, fmt.Errorf("getting headers: %w", err) + } + return convertMapListString(headers), nil } func (c HeadersEntityConverter) String() string { @@ -47,7 +55,11 @@ func (c HeadersEntityConverter) String() string { type QueryEntityConverter struct{} func (c QueryEntityConverter) Convert(e wrapper.Entity) (interface{}, error) { - return convertMapListString(e.GetURL().Query()), nil + url, err := e.GetURL() + if err != nil { + return nil, fmt.Errorf("getting url: %w", err) + } + return convertMapListString(url.Query()), nil } func (c QueryEntityConverter) String() string { @@ -71,7 +83,11 @@ func (c BodyEntityConverter) String() string { type PathEntityConverter struct{} func (c PathEntityConverter) Convert(e wrapper.Entity) (interface{}, error) { - return e.GetURL().Path, nil + url, err := e.GetURL() + if err != nil { + return nil, fmt.Errorf("getting url: %w", err) + } + return url.Path, nil } func (c PathEntityConverter) String() string { @@ -92,6 +108,20 @@ func (c FormEntityConverter) String() string { return "form" } +type RawEntityConverter struct{} + +func (c RawEntityConverter) Convert(e wrapper.Entity) (interface{}, error) { + data, err := e.GetRaw() + if err != nil { + return nil, fmt.Errorf("getting raw data: %w", err) + } + return data, nil +} + +func (c RawEntityConverter) String() string { + return "raw" +} + func convertMapListString(data map[string][]string) map[string]interface{} { result := make(map[string]interface{}) for k, v := range data { diff --git a/internal/proxy/tcp/filters/interface.go b/internal/filters/interface.go similarity index 81% rename from internal/proxy/tcp/filters/interface.go rename to internal/filters/interface.go index 333ed9b..7e4bf01 100644 --- a/internal/proxy/tcp/filters/interface.go +++ b/internal/filters/interface.go @@ -2,12 +2,20 @@ package filters import ( "fmt" + "go.uber.org/atomic" + "goxy/internal/common" + "goxy/internal/wrapper" ) type Rule interface { - Apply(ctx *common.ProxyContext, buf []byte, ingress bool) (bool, error) + Apply(ctx *common.ProxyContext, i interface{}) (bool, error) + fmt.Stringer +} + +type EntityConverter interface { + Convert(e wrapper.Entity) (interface{}, error) fmt.Stringer } diff --git a/internal/filters/rule_wrappers.go b/internal/filters/rule_wrappers.go new file mode 100644 index 0000000..e58f947 --- /dev/null +++ b/internal/filters/rule_wrappers.go @@ -0,0 +1,138 @@ +package filters + +import ( + "fmt" + "strings" + + "goxy/internal/common" + "goxy/internal/wrapper" +) + +func NewIngressWrapper(r Rule, _ common.RuleConfig) Rule { + return CompositeAndRule{ + rules: []Rule{IngressRule{}, r}, + } +} + +func NewEgressWrapper(r Rule, cfg common.RuleConfig) Rule { + return CompositeNotRule{rule: NewIngressWrapper(r, cfg)} +} + +func NewNotWrapper(r Rule, _ common.RuleConfig) Rule { + return CompositeNotRule{rule: r} +} + +func NewAnyWrapper(r Rule, _ common.RuleConfig) Rule { + return AnyWrapper{r} +} + +func NewFieldWrapper(r Rule, cfg common.RuleConfig) Rule { + fieldChain := strings.Split(cfg.Field, ".") + return FieldWrapper{r, fieldChain} +} + +type AnyWrapper struct { + rule Rule +} + +func (w AnyWrapper) Apply(ctx *common.ProxyContext, v interface{}) (bool, error) { + switch v.(type) { + case map[string]interface{}: + for _, v := range v.(map[string]interface{}) { + res, err := w.rule.Apply(ctx, v) + if err != nil { + return false, fmt.Errorf("in rule %v: %w", w.rule, err) + } + if res { + return true, nil + } + } + return false, nil + + case []interface{}: + for _, v := range v.([]interface{}) { + res, err := w.rule.Apply(ctx, v) + if err != nil { + return false, fmt.Errorf("in rule %v: %w", w.rule, err) + } + if res { + return true, nil + } + } + return false, nil + + case []string: + for _, v := range v.([]string) { + res, err := w.rule.Apply(ctx, v) + if err != nil { + return false, fmt.Errorf("in rule %v: %w", w.rule, err) + } + if res { + return true, nil + } + } + return false, nil + } + + return false, fmt.Errorf("data type %T: %w", v, ErrInvalidInputType) +} + +func (w AnyWrapper) String() string { + return fmt.Sprintf("any %s", w.rule) +} + +type FieldWrapper struct { + rule Rule + fieldChain []string +} + +func (w FieldWrapper) Apply(ctx *common.ProxyContext, data interface{}) (bool, error) { + result := data + for _, f := range w.fieldChain { + switch result.(type) { + case map[string]interface{}: + next, ok := result.(map[string]interface{})[f] + if !ok { + return false, nil + } + result = next + default: + return false, nil + } + } + res, err := w.rule.Apply(ctx, result) + if err != nil { + return false, fmt.Errorf("in rule %v: %w", w.rule, err) + } + return res, nil +} + +func (w FieldWrapper) String() string { + fieldRepr := strings.Join(w.fieldChain, ".") + return fmt.Sprintf("field '%s' %s", fieldRepr, w.rule) +} + +type ConvertingWrapper struct { + rule Rule + converter EntityConverter +} + +func (w ConvertingWrapper) Apply(ctx *common.ProxyContext, v interface{}) (bool, error) { + e, ok := v.(wrapper.Entity) + if !ok { + return false, fmt.Errorf("not an entity: %v", v) + } + data, err := w.converter.Convert(e) + if err != nil { + return false, fmt.Errorf("converting with %s: %w", w.converter, err) + } + res, err := w.rule.Apply(ctx, data) + if err != nil { + return false, fmt.Errorf("in rule %v: %w", w.rule, err) + } + return res, nil +} + +func (w ConvertingWrapper) String() string { + return fmt.Sprintf("%s %s", w.converter, w.rule) +} diff --git a/internal/filters/rules.go b/internal/filters/rules.go new file mode 100644 index 0000000..020a925 --- /dev/null +++ b/internal/filters/rules.go @@ -0,0 +1,188 @@ +package filters + +import ( + "bytes" + "errors" + "fmt" + "regexp" + "strings" + + "goxy/internal/common" + "goxy/internal/wrapper" +) + +var ( + ErrInvalidRuleArgs = errors.New("invalid rule arguments") + ErrInvalidInputType = errors.New("invalid input data") +) + +func NewContainsRule(_ RuleSet, cfg common.RuleConfig) (Rule, error) { + if len(cfg.Args) != 1 { + return nil, ErrInvalidRuleArgs + } + return ContainsRule{cfg.Args[0]}, nil +} +func NewIContainsRule(_ RuleSet, cfg common.RuleConfig) (Rule, error) { + if len(cfg.Args) != 1 { + return nil, ErrInvalidRuleArgs + } + return IContainsRule{strings.ToLower(cfg.Args[0])}, nil +} + +func NewRegexRule(_ RuleSet, cfg common.RuleConfig) (Rule, error) { + if len(cfg.Args) != 1 { + return nil, ErrInvalidRuleArgs + } + re, err := regexp.Compile(cfg.Args[0]) + if err != nil { + return nil, fmt.Errorf("compiling regex: %w", err) + } + return RegexRule{re}, nil +} + +type IngressRule struct{} + +func (r IngressRule) Apply(_ *common.ProxyContext, v interface{}) (bool, error) { + e, ok := v.(wrapper.Entity) + if !ok { + return false, fmt.Errorf("can only work on entities, not %v %T", v, v) + } + return e.GetIngress(), nil +} + +func (r IngressRule) String() string { + return "ingress" +} + +type ContainsRule struct { + value string +} + +func (r ContainsRule) Apply(_ *common.ProxyContext, v interface{}) (bool, error) { + switch v.(type) { + case wrapper.Entity: + body, err := v.(wrapper.Entity).GetBody() + if err != nil { + return false, fmt.Errorf("getting body: %w", err) + } + return bytes.Contains(body, []byte(r.value)), nil + case map[string]interface{}: + for k := range v.(map[string]interface{}) { + if k == r.value { + return true, nil + } + } + return false, nil + case []interface{}: + for _, v := range v.([]interface{}) { + switch v.(type) { + case string: + if strings.Contains(v.(string), r.value) { + return true, nil + } + case []byte: + if bytes.Contains(v.([]byte), []byte(r.value)) { + return true, nil + } + } + } + return false, nil + case []string: + for _, s := range v.([]string) { + if s == r.value { + return true, nil + } + } + return false, nil + case string: + return strings.Contains(v.(string), r.value), nil + case []byte: + return bytes.Contains(v.([]byte), []byte(r.value)), nil + } + + return false, fmt.Errorf("data type %T: %w", v, ErrInvalidInputType) +} + +func (r ContainsRule) String() string { + return fmt.Sprintf("contains '%s'", r.value) +} + +type IContainsRule struct { + value string +} + +func (r IContainsRule) Apply(_ *common.ProxyContext, v interface{}) (bool, error) { + switch v.(type) { + case wrapper.Entity: + body, err := v.(wrapper.Entity).GetBody() + if err != nil { + return false, fmt.Errorf("getting body: %w", err) + } + return bytes.Contains(bytes.ToLower(body), []byte(r.value)), nil + case map[string]interface{}: + for k := range v.(map[string]interface{}) { + if strings.ToLower(k) == r.value { + return true, nil + } + } + return false, nil + case []interface{}: + for _, v := range v.([]interface{}) { + switch v.(type) { + case string: + if strings.Contains(strings.ToLower(v.(string)), r.value) { + return true, nil + } + case []byte: + if bytes.Contains(bytes.ToLower(v.([]byte)), []byte(r.value)) { + return true, nil + } + } + } + return false, nil + + case []string: + for _, s := range v.([]string) { + if strings.ToLower(s) == r.value { + return true, nil + } + } + return false, nil + + case string: + return strings.Contains(strings.ToLower(v.(string)), r.value), nil + case []byte: + return bytes.Contains(bytes.ToLower(v.([]byte)), []byte(r.value)), nil + } + + return false, fmt.Errorf("data type %T: %w", v, ErrInvalidInputType) +} + +func (r IContainsRule) String() string { + return fmt.Sprintf("icontains '%s'", r.value) +} + +type RegexRule struct { + re *regexp.Regexp +} + +func (r RegexRule) Apply(_ *common.ProxyContext, v interface{}) (bool, error) { + switch v.(type) { + case wrapper.Entity: + body, err := v.(wrapper.Entity).GetBody() + if err != nil { + return false, fmt.Errorf("getting body: %w", err) + } + return r.re.Match(body), nil + case string: + return r.re.MatchString(v.(string)), nil + case []byte: + return r.re.Match(v.([]byte)), nil + } + + return false, fmt.Errorf("data type %T: %w", v, ErrInvalidInputType) +} + +func (r RegexRule) String() string { + return fmt.Sprintf("regex '%s'", r.re) +} diff --git a/internal/filters/ruleset.go b/internal/filters/ruleset.go new file mode 100644 index 0000000..70a4b25 --- /dev/null +++ b/internal/filters/ruleset.go @@ -0,0 +1,83 @@ +package filters + +import ( + "fmt" + "strings" + + "goxy/internal/common" +) + +type RuleSet struct { + Rules map[string]Rule +} + +func (rs *RuleSet) GetRule(name string) (Rule, bool) { + if rule, ok := rs.Rules[name]; ok { + return rule, true + } + if rule, ok := DefaultRules[name]; ok { + return rule, true + } + return nil, false +} + +func NewRuleSet(cfg []common.RuleConfig) (*RuleSet, error) { + rs := RuleSet{Rules: make(map[string]Rule)} + + for _, rc := range cfg { + tokens := strings.Split(rc.Type, "::") + if len(tokens) == 0 { + return nil, fmt.Errorf("invalid rule: %s", rc.Type) + } + + var ( + err error + rule Rule + converted bool + ) + + lastToken := tokens[len(tokens)-1] + if creator, ok := DefaultRuleCreators[lastToken]; ok { + // default rule type + if rule, err = creator(rs, rc); err != nil { + return nil, fmt.Errorf("creating rule %s: %w", lastToken, err) + } + } else { + return nil, fmt.Errorf("invalid rule %s: last token invalid", rc.Type) + } + + for i := len(tokens) - 2; i >= 0; i -= 1 { + ruleName := tokens[i] + if entityConverter, ok := DefaultEntityConverters[ruleName]; ok { + if converted { + return nil, fmt.Errorf("double conversion in %s", rc.Type) + } + converted = true + + // regular rules started, need to convert. + // if field is specified for rule, we need to wrap it into FieldWrapper. + if rc.Field != "" { + rule = NewFieldWrapper(rule, rc) + } + rule = ConvertingWrapper{ + rule: rule, + converter: entityConverter, + } + continue + } else if wrapperCreator, ok := DefaultRuleWrappers[ruleName]; ok { + rule = wrapperCreator(rule, rc) + } else { + return nil, fmt.Errorf("unexpected token %s for %s", ruleName, rc.Type) + } + } + if !converted { + rule = ConvertingWrapper{ + rule: rule, + converter: RawEntityConverter{}, + } + } + rs.Rules[rc.Name] = rule + } + + return &rs, nil +} diff --git a/internal/filters/transformers.go b/internal/filters/transformers.go new file mode 100644 index 0000000..1cdc472 --- /dev/null +++ b/internal/filters/transformers.go @@ -0,0 +1,50 @@ +package filters + +// +//import ( +// "bytes" +// "fmt" +// "regexp" +// +// "github.com/sirupsen/logrus" +// +// "goxy/internal/common" +// "goxy/internal/wrapper" +//) +// +//func NewTransformVolgaCTF() Rule { +// return TransformVolgaCTF{regex: regexp.MustCompile("VolgaCTF{([^}]+)}")} +//} +// +//type TransformVolgaCTF struct { +// regex *regexp.Regexp +//} +// +//func (t TransformVolgaCTF) Apply(_ *common.ProxyContext, e wrapper.Entity) (bool, error) { +// // TODO: apply to all fields (headers, etc) +// body, err := e.GetBody() +// if err != nil { +// return false, fmt.Errorf("get body: %w", err) +// } +// logrus.Debugf("Got body: %s", string(body)) +// matches := t.regex.FindAllSubmatch(body, -1) +// logrus.Debugf("Got matches: %+v", matches) +// for _, match := range matches { +// body = bytes.ReplaceAll(body, match[1], obfuscateMatch(match[1])) +// } +// logrus.Debugf("New body: %s", string(body)) +// e.SetBody(body) +// return len(matches) > 0, nil +//} +// +//func (t TransformVolgaCTF) String() string { +// return "transform-VolgaCTF" +//} +// +//func obfuscateMatch(match []byte) []byte { +// result := make([]byte, len(match)) +// for i := 0; i+1 < len(result); i += 2 { +// result[i], result[i+1] = match[i+1], match[i] +// } +// return result +//} diff --git a/internal/grpcauth/token.go b/internal/grpcauth/token.go new file mode 100644 index 0000000..1290bcc --- /dev/null +++ b/internal/grpcauth/token.go @@ -0,0 +1,48 @@ +package grpcauth + +import ( + "context" + + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" +) + +const authKey = "authorization" + +func NewClientInterceptor(key string) *ClientTokenInterceptor { + return &ClientTokenInterceptor{token: key} +} + +type ClientTokenInterceptor struct { + token string +} + +func (interceptor *ClientTokenInterceptor) attachToken(ctx context.Context) context.Context { + return metadata.AppendToOutgoingContext(ctx, authKey, interceptor.token) +} + +func (interceptor *ClientTokenInterceptor) Unary() grpc.UnaryClientInterceptor { + return func( + ctx context.Context, + method string, + req, reply interface{}, + cc *grpc.ClientConn, + invoker grpc.UnaryInvoker, + opts ...grpc.CallOption, + ) error { + return invoker(interceptor.attachToken(ctx), method, req, reply, cc, opts...) + } +} + +func (interceptor *ClientTokenInterceptor) Stream() grpc.StreamClientInterceptor { + return func( + ctx context.Context, + desc *grpc.StreamDesc, + cc *grpc.ClientConn, + method string, + streamer grpc.Streamer, + opts ...grpc.CallOption, + ) (grpc.ClientStream, error) { + return streamer(interceptor.attachToken(ctx), desc, cc, method, opts...) + } +} diff --git a/internal/proxy/http/filters/interface.go b/internal/proxy/http/filters/interface.go deleted file mode 100644 index 9e33c1f..0000000 --- a/internal/proxy/http/filters/interface.go +++ /dev/null @@ -1,65 +0,0 @@ -package filters - -import ( - "fmt" - "go.uber.org/atomic" - "goxy/internal/common" - "goxy/internal/proxy/http/wrapper" -) - -type Rule interface { - Apply(ctx *common.ProxyContext, e wrapper.Entity) (bool, error) - fmt.Stringer -} - -type RawRule interface { - Apply(ctx *common.ProxyContext, data interface{}) (bool, error) - fmt.Stringer -} - -type EntityConverter interface { - Convert(e wrapper.Entity) (interface{}, error) - fmt.Stringer -} - -type RuleCreator func(rs RuleSet, cfg common.RuleConfig) (Rule, error) -type RawRuleCreator func(cfg common.RuleConfig) (RawRule, error) - -type RuleWrapperCreator func(rule Rule, cfg common.RuleConfig) Rule -type RawRuleWrapperCreator func(rule RawRule, cfg common.RuleConfig) RawRule - -type Filter struct { - Rule Rule - Verdict common.Verdict - - alert atomic.Bool - disabled atomic.Bool -} - -func (f Filter) IsEnabled() bool { - return !f.disabled.Load() -} - -func (f Filter) GetAlert() bool { - return f.alert.Load() -} - -func (f *Filter) SetEnabled(enabled bool) { - f.disabled.Store(!enabled) -} - -func (f *Filter) SetAlert(alert bool) { - f.alert.Store(alert) -} - -func (f Filter) GetRule() common.Rule { - return f.Rule -} - -func (f Filter) GetVerdict() common.Verdict { - return f.Verdict -} - -func (f Filter) String() string { - return fmt.Sprintf("if %s: %s", f.Rule, f.Verdict) -} diff --git a/internal/proxy/http/filters/raw_rule_wrappers.go b/internal/proxy/http/filters/raw_rule_wrappers.go deleted file mode 100644 index 82a992e..0000000 --- a/internal/proxy/http/filters/raw_rule_wrappers.go +++ /dev/null @@ -1,177 +0,0 @@ -package filters - -import ( - "fmt" - "github.com/sirupsen/logrus" - "goxy/internal/common" - "goxy/internal/proxy/http/wrapper" - "strings" -) - -func NewAnyWrapper(r RawRule, _ common.RuleConfig) RawRule { - return AnyWrapper{r} -} - -func NewArrayWrapper(r RawRule, _ common.RuleConfig) RawRule { - return ArrayWrapper{r} -} - -func NewFieldWrapper(r RawRule, cfg common.RuleConfig) RawRule { - fieldChain := strings.Split(cfg.Field, ".") - return FieldWrapper{r, fieldChain} -} - -func NewNotWrapperRaw(r RawRule, _ common.RuleConfig) RawRule { - return RawNotWrapper{r} -} - -func NewRawRuleConverter(rule RawRule, ec EntityConverter) Rule { - return RawRuleConverterWrapper{rule, ec} -} - -type AnyWrapper struct { - rule RawRule -} - -func (w AnyWrapper) Apply(ctx *common.ProxyContext, data interface{}) (bool, error) { - switch data.(type) { - case map[string]interface{}: - for _, v := range data.(map[string]interface{}) { - res, err := w.rule.Apply(ctx, v) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", w.rule, err) - } - if res { - return true, nil - } - } - - case []interface{}: - for _, v := range data.([]interface{}) { - res, err := w.rule.Apply(ctx, v) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", w.rule, err) - } - if res { - return true, nil - } - } - - case []string: - for _, v := range data.([]string) { - res, err := w.rule.Apply(ctx, v) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", w.rule, err) - } - if res { - return true, nil - } - } - - default: - return false, fmt.Errorf("data type %T: %w", data, ErrInvalidInputType) - } - - return false, nil -} - -func (w AnyWrapper) String() string { - return fmt.Sprintf("any %s", w.rule) -} - -type ArrayWrapper struct { - rule RawRule -} - -func (w ArrayWrapper) Apply(ctx *common.ProxyContext, data interface{}) (bool, error) { - switch data.(type) { - case []interface{}: - res, err := w.rule.Apply(ctx, data.([]interface{})) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", w.rule, err) - } - return res, nil - case []string: - res, err := w.rule.Apply(ctx, data.([]string)) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", w.rule, err) - } - return res, nil - default: - return false, nil - } -} - -func (w ArrayWrapper) String() string { - return fmt.Sprintf("is array and %s", w.rule) -} - -type FieldWrapper struct { - rule RawRule - fieldChain []string -} - -func (w FieldWrapper) Apply(ctx *common.ProxyContext, data interface{}) (bool, error) { - result := data - for _, f := range w.fieldChain { - switch result.(type) { - case map[string]interface{}: - converted := result.(map[string]interface{}) - next, ok := converted[f] - if !ok { - return false, nil - } - result = next - default: - return false, nil - } - } - res, err := w.rule.Apply(ctx, result) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", w.rule, err) - } - return res, nil -} - -func (w FieldWrapper) String() string { - fieldRepr := strings.Join(w.fieldChain, ".") - return fmt.Sprintf("field '%s' %s", fieldRepr, w.rule) -} - -type RawNotWrapper struct { - rule RawRule -} - -func (w RawNotWrapper) Apply(ctx *common.ProxyContext, data interface{}) (bool, error) { - res, err := w.rule.Apply(ctx, data) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", w.rule, err) - } - return !res, nil -} - -func (w RawNotWrapper) String() string { - return fmt.Sprintf("not (%s)", w.rule) -} - -type RawRuleConverterWrapper struct { - rule RawRule - ec EntityConverter -} - -func (w RawRuleConverterWrapper) Apply(ctx *common.ProxyContext, e wrapper.Entity) (bool, error) { - data, err := w.ec.Convert(e) - if err != nil { - logrus.Debugf("Entity converter returned an error: %v", err) - return false, nil - } - res, err := w.rule.Apply(ctx, data) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", w.rule, err) - } - return res, nil -} - -func (w RawRuleConverterWrapper) String() string { - return fmt.Sprintf("%s %s", w.ec, w.rule) -} diff --git a/internal/proxy/http/filters/rule_wrappers.go b/internal/proxy/http/filters/rule_wrappers.go deleted file mode 100644 index 2006bf5..0000000 --- a/internal/proxy/http/filters/rule_wrappers.go +++ /dev/null @@ -1,73 +0,0 @@ -package filters - -import ( - "fmt" - "goxy/internal/common" - "goxy/internal/proxy/http/wrapper" -) - -func NewIngressWrapper(rule Rule, _ common.RuleConfig) Rule { - return IngressWrapper{rule} -} - -func NewEgressWrapper(rule Rule, _ common.RuleConfig) Rule { - return EgressWrapper{rule} -} - -func NewNotWrapper(rule Rule, _ common.RuleConfig) Rule { - return NotWrapper{rule} -} - -type IngressWrapper struct { - rule Rule -} - -func (w IngressWrapper) Apply(ctx *common.ProxyContext, e wrapper.Entity) (bool, error) { - if !e.GetIngress() { - return false, nil - } - res, err := w.rule.Apply(ctx, e) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", w.rule, err) - } - return res, nil -} - -func (w IngressWrapper) String() string { - return fmt.Sprintf("ingress and %s", w.rule) -} - -type EgressWrapper struct { - rule Rule -} - -func (w EgressWrapper) Apply(ctx *common.ProxyContext, e wrapper.Entity) (bool, error) { - if e.GetIngress() { - return false, nil - } - res, err := w.rule.Apply(ctx, e) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", w.rule, err) - } - return res, nil -} - -func (w EgressWrapper) String() string { - return fmt.Sprintf("egress and %s", w.rule) -} - -type NotWrapper struct { - rule Rule -} - -func (w NotWrapper) Apply(ctx *common.ProxyContext, e wrapper.Entity) (bool, error) { - res, err := w.rule.Apply(ctx, e) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", w.rule, err) - } - return !res, nil -} - -func (w NotWrapper) String() string { - return fmt.Sprintf("not (%s)", w.rule) -} diff --git a/internal/proxy/http/filters/rules.go b/internal/proxy/http/filters/rules.go deleted file mode 100644 index 4364f2e..0000000 --- a/internal/proxy/http/filters/rules.go +++ /dev/null @@ -1,150 +0,0 @@ -package filters - -import ( - "bytes" - "errors" - "fmt" - "goxy/internal/common" - "goxy/internal/proxy/http/wrapper" - "regexp" - "strings" -) - -var ( - ErrInvalidRuleArgs = errors.New("invalid rule arguments") - ErrInvalidInputType = errors.New("invalid input data") -) - -func NewContainsRawRule(cfg common.RuleConfig) (RawRule, error) { - if len(cfg.Args) != 1 { - return nil, ErrInvalidRuleArgs - } - return ContainsRawRule{cfg.Args[0]}, nil -} - -func NewIContainsRawRule(cfg common.RuleConfig) (RawRule, error) { - if len(cfg.Args) != 1 { - return nil, ErrInvalidRuleArgs - } - return IContainsRawRule{strings.ToLower(cfg.Args[0])}, nil -} - -func NewRegexRawRule(cfg common.RuleConfig) (RawRule, error) { - if len(cfg.Args) != 1 { - return nil, ErrInvalidRuleArgs - } - re, err := regexp.Compile(cfg.Args[0]) - if err != nil { - return nil, fmt.Errorf("compiling regex: %w", err) - } - return RegexRawRule{re}, nil -} - -type IngressRule struct{} - -func (r IngressRule) Apply(_ *common.ProxyContext, e wrapper.Entity) (bool, error) { - return e.GetIngress(), nil -} - -func (r IngressRule) String() string { - return "ingress" -} - -type ContainsRawRule struct { - value string -} - -func (r ContainsRawRule) Apply(_ *common.ProxyContext, data interface{}) (bool, error) { - stringHandler := func(s string) bool { - return strings.Contains(s, r.value) - } - bytesHandler := func(b []byte) bool { - return bytes.Contains(b, []byte(r.value)) - } - return processGenericMatchRule(stringHandler, bytesHandler, data) -} - -func (r ContainsRawRule) String() string { - return fmt.Sprintf("contains '%s'", r.value) -} - -type IContainsRawRule struct { - value string -} - -func (r IContainsRawRule) Apply(_ *common.ProxyContext, data interface{}) (bool, error) { - stringHandler := func(s string) bool { - return strings.Contains(strings.ToLower(s), r.value) - } - bytesHandler := func(b []byte) bool { - return bytes.Contains(bytes.ToLower(b), []byte(r.value)) - } - return processGenericMatchRule(stringHandler, bytesHandler, data) -} - -func (r IContainsRawRule) String() string { - return fmt.Sprintf("icontains '%s'", r.value) -} - -type RegexRawRule struct { - re *regexp.Regexp -} - -func (r RegexRawRule) Apply(_ *common.ProxyContext, data interface{}) (bool, error) { - stringHandler := func(s string) bool { - return r.re.MatchString(s) - } - bytesHandler := func(b []byte) bool { - return r.re.Match(b) - } - return processGenericMatchRule(stringHandler, bytesHandler, data) -} - -func (r RegexRawRule) String() string { - return fmt.Sprintf("regex '%s'", r.re) -} - -func processGenericMatchRule(sh func(string) bool, bh func([]byte) bool, data interface{}) (bool, error) { - switch data.(type) { - case map[string]interface{}: - for _, v := range data.(map[string]interface{}) { - switch v.(type) { - case string: - if sh(v.(string)) { - return true, nil - } - case []byte: - if bh(v.([]byte)) { - return true, nil - } - } - } - case []interface{}: - for _, v := range data.([]interface{}) { - switch v.(type) { - case string: - if sh(v.(string)) { - return true, nil - } - case []byte: - if bh(v.([]byte)) { - return true, nil - } - } - } - case []string: - for _, v := range data.([]string) { - if sh(v) { - return true, nil - } - } - case string: - return sh(data.(string)), nil - case []byte: - return bh(data.([]byte)), nil - default: - return false, fmt.Errorf("data type %T: %w", data, ErrInvalidInputType) - } - - return false, nil -} diff --git a/internal/proxy/http/filters/ruleset.go b/internal/proxy/http/filters/ruleset.go deleted file mode 100644 index a1f0b6b..0000000 --- a/internal/proxy/http/filters/ruleset.go +++ /dev/null @@ -1,99 +0,0 @@ -package filters - -import ( - "fmt" - "goxy/internal/common" - "strings" -) - -type RuleSet struct { - Rules map[string]Rule -} - -func (rs *RuleSet) GetRule(name string) (Rule, bool) { - if rule, ok := rs.Rules[name]; ok { - return rule, true - } - if rule, ok := DefaultRules[name]; ok { - return rule, true - } - return nil, false -} - -func NewRuleSet(cfg []common.RuleConfig) (*RuleSet, error) { - rs := RuleSet{Rules: make(map[string]Rule)} - - for _, rc := range cfg { - if strings.HasPrefix(rc.Type, "http::") { - tokens := strings.Split(rc.Type, "::") - if len(tokens) < 2 { - return nil, fmt.Errorf("invalid rule: %s", rc.Type) - } - - var ( - ok bool - err error - rawRule RawRule - rawCreator RawRuleCreator - creator RuleCreator - rule Rule - ) - - // Some block at the end of rules (can be empty) contains only raw rules. - // Rules before are regular rules, and between these two blocks we need to insert - // the RawRuleConverterWrapper. - - // the last rule in chain must be either the composite rule or raw rule. - lastToken := tokens[len(tokens)-1] - if rule, ok = DefaultTransformers[lastToken]; ok { - } else if creator, ok = DefaultRuleCreators[lastToken]; ok { - // default rule type - if rule, err = creator(rs, rc); err != nil { - return nil, fmt.Errorf("creating rule %s: %w", lastToken, err) - } - } else if rawCreator, ok = DefaultRawRuleCreators[lastToken]; ok { - // rule is regular raw rule - if rawRule, err = rawCreator(rc); err != nil { - return nil, fmt.Errorf("creating raw rule %s: %w", lastToken, err) - } - } else { - return nil, fmt.Errorf("invalid rule %s: last token invalid", rc.Type) - } - - for i := len(tokens) - 2; i > 0; i -= 1 { - ruleName := tokens[i] - if rawRule != nil { - if wrapperCreator, ok := DefaultRawRuleWrappers[ruleName]; ok { - rawRule = wrapperCreator(rawRule, rc) - continue - } else if entityConverter, ok := DefaultEntityConverters[ruleName]; ok { - // regular rules started, need to convert. - // if field is specified for rule, we need to wrap it into FieldWrapper. - if rc.Field != "" { - rawRule = NewFieldWrapper(rawRule, rc) - } - rule = NewRawRuleConverter(rawRule, entityConverter) - rawRule = nil - continue - } else { - return nil, fmt.Errorf("no entity converter with name %s for rule %s", ruleName, rc.Type) - } - } - - if wrapperCreator, ok := DefaultRuleWrappers[ruleName]; ok { - rule = wrapperCreator(rule, rc) - } else { - return nil, fmt.Errorf("no wrapper for name %s", ruleName) - } - } - - if rawRule != nil { - return nil, fmt.Errorf("entity converter for %s not specified", rc.Type) - } - - rs.Rules[rc.Name] = rule - } - } - - return &rs, nil -} diff --git a/internal/proxy/http/filters/transformers.go b/internal/proxy/http/filters/transformers.go deleted file mode 100644 index 6274f57..0000000 --- a/internal/proxy/http/filters/transformers.go +++ /dev/null @@ -1,47 +0,0 @@ -package filters - -import ( - "bytes" - "fmt" - "github.com/sirupsen/logrus" - "goxy/internal/common" - "goxy/internal/proxy/http/wrapper" - "regexp" -) - -func NewTransformVolgaCTF() Rule { - return TransformVolgaCTF{regex: regexp.MustCompile("VolgaCTF{([^}]+)}")} -} - -type TransformVolgaCTF struct { - regex *regexp.Regexp -} - -func (t TransformVolgaCTF) Apply(_ *common.ProxyContext, e wrapper.Entity) (bool, error) { - // TODO: apply to all fields (headers, etc) - body, err := e.GetBody() - if err != nil { - return false, fmt.Errorf("get body: %w", err) - } - logrus.Debugf("Got body: %s", string(body)) - matches := t.regex.FindAllSubmatch(body, -1) - logrus.Debugf("Got matches: %+v", matches) - for _, match := range matches { - body = bytes.ReplaceAll(body, match[1], obfuscateMatch(match[1])) - } - logrus.Debugf("New body: %s", string(body)) - e.SetBody(body) - return len(matches) > 0, nil -} - -func (t TransformVolgaCTF) String() string { - return "transform-VolgaCTF" -} - -func obfuscateMatch(match []byte) []byte { - result := make([]byte, len(match)) - for i := 0; i+1 < len(result); i += 2 { - result[i], result[i+1] = match[i+1], match[i] - } - return result -} diff --git a/internal/proxy/http/proxy.go b/internal/proxy/http/proxy.go index c073d27..f6d58cc 100644 --- a/internal/proxy/http/proxy.go +++ b/internal/proxy/http/proxy.go @@ -4,15 +4,21 @@ import ( "context" "errors" "fmt" - "go.uber.org/atomic" - "goxy/internal/common" - "goxy/internal/proxy/http/filters" - "goxy/internal/proxy/http/wrapper" "io" + "net" "net/http" + "strconv" "sync" "time" + "github.com/google/uuid" + "go.uber.org/atomic" + + "goxy/internal/common" + "goxy/internal/export" + "goxy/internal/filters" + "goxy/internal/wrapper" + "github.com/sirupsen/logrus" ) @@ -21,7 +27,7 @@ var ( ErrInvalidFilter = errors.New("no such filter") ) -func NewProxy(cfg common.ServiceConfig, rs *filters.RuleSet) (*Proxy, error) { +func NewProxy(cfg common.ServiceConfig, rs *filters.RuleSet, pc *export.ProducerClient) (*Proxy, error) { fts := make([]filters.Filter, 0, len(cfg.Filters)) for _, f := range cfg.Filters { rule, ok := rs.GetRule(f.Rule) @@ -44,11 +50,13 @@ func NewProxy(cfg common.ServiceConfig, rs *filters.RuleSet) (*Proxy, error) { p := &Proxy{ ListenAddr: cfg.Listen, TargetAddr: cfg.Target, + Name: cfg.Name, serviceConfig: cfg, logger: logger, filters: fts, wg: new(sync.WaitGroup), + producer: pc, } return p, nil } @@ -56,6 +64,7 @@ func NewProxy(cfg common.ServiceConfig, rs *filters.RuleSet) (*Proxy, error) { type Proxy struct { ListenAddr string TargetAddr string + Name string serviceConfig common.ServiceConfig closing bool @@ -65,6 +74,7 @@ type Proxy struct { wg *sync.WaitGroup logger *logrus.Entry filters []filters.Filter + producer *export.ProducerClient } func (p Proxy) GetListening() bool { @@ -119,7 +129,7 @@ func (p Proxy) GetConfig() *common.ServiceConfig { } func (p Proxy) String() string { - return fmt.Sprintf("HTTP proxy %s", p.ListenAddr) + return fmt.Sprintf("HTTP proxy %s (%s)", p.Name, p.ListenAddr) } func (p Proxy) GetFilters() []common.Filter { @@ -173,10 +183,16 @@ func (p Proxy) getHandler() http.HandlerFunc { return w, nil } - reqLogger := p.logger.WithField("side", "request") - respLogger := p.logger.WithField("side", "response") - return func(w http.ResponseWriter, r *http.Request) { + reqLogger := p.logger.WithFields(logrus.Fields{ + "side": "request", + "addr": r.RemoteAddr, + }) + respLogger := p.logger.WithFields(logrus.Fields{ + "side": "response", + "addr": r.RemoteAddr, + }) + reqLogger.Debugf("New request: %v", r) if !p.GetListening() { @@ -200,6 +216,13 @@ func (p Proxy) getHandler() http.HandlerFunc { return } + base := p.getBasePacket(r) + if err := p.exportEntity(r.Context(), reqEntity, base, reqLogger); err != nil { + reqLogger.Errorf("Error exporting packet: %v", err) + handleError(w) + return + } + if pctx.GetFlag(common.DropFlag) { reqLogger.Debugf("Dropping connection") handleDrop(w) @@ -231,6 +254,11 @@ func (p Proxy) getHandler() http.HandlerFunc { handleError(w) return } + if err := p.exportEntity(r.Context(), respEntity, base, respLogger); err != nil { + respLogger.Errorf("Error exporting packet: %v", err) + handleError(w) + return + } if pctx.GetFlag(common.DropFlag) { respLogger.Debugf("Dropping connection") @@ -253,6 +281,46 @@ func (p Proxy) getHandler() http.HandlerFunc { } } +func (p *Proxy) getBasePacket(r *http.Request) *export.BasePacket { + srcHost, srcPort := splitAddrSafe(r.RemoteAddr, 0) + dstHost, dstPort := splitAddrSafe(r.Host, 0) + + return &export.BasePacket{ + Source: fmt.Sprintf("goxy-%s", p.Name), + Endpoints: &export.EndpointData{ + IPSrc: srcHost, + IPDst: dstHost, + PortSrc: srcPort, + PortDst: dstPort, + }, + Proto: "tcp", + ProducerStreamID: uuid.New().String(), + } +} + +func (p *Proxy) exportEntity(ctx context.Context, e wrapper.Entity, base *export.BasePacket, logger *logrus.Entry) error { + if p.producer == nil { + logger.Debug("Exporter is disabled") + return nil + } + body, err := e.GetRaw() + if err != nil { + return fmt.Errorf("getting raw data: %w", err) + } + reqPacket := export.Packet{ + BasePacket: base, + Content: body, + CaptureTime: time.Now(), + FilterData: 0, // TODO: add filters. + Inbound: e.GetIngress(), + Reversed: !e.GetIngress(), + } + if err := p.producer.Send(ctx, &reqPacket); err != nil { + logger.Warningf("Error sending to producer: %v", err) + } + return nil +} + func (p *Proxy) serve() { defer p.wg.Done() @@ -279,3 +347,16 @@ func (p *Proxy) serve() { } p.logger.Infof("Server shutdown complete") } + +func splitAddrSafe(addr string, defPort int) (host string, port int) { + host, portStr, err := net.SplitHostPort(addr) + if err != nil { + host = "0.0.0.0" + port = defPort + } else { + if port, err = strconv.Atoi(portStr); err != nil { + port = defPort + } + } + return host, port +} diff --git a/internal/proxy/manager.go b/internal/proxy/manager.go index 3c992eb..2b61702 100644 --- a/internal/proxy/manager.go +++ b/internal/proxy/manager.go @@ -4,43 +4,42 @@ import ( "context" "errors" "fmt" + "sync" + "time" + "goxy/internal/common" + "goxy/internal/export" + "goxy/internal/filters" "goxy/internal/models" "goxy/internal/proxy/http" "goxy/internal/proxy/tcp" - "sync" - "time" "github.com/sirupsen/logrus" - - httpfilters "goxy/internal/proxy/http/filters" - tcpfilters "goxy/internal/proxy/tcp/filters" ) var ( ErrNoSuchProxy = errors.New("no such proxy") ) -func NewManager(cfg *common.ProxyConfig) (*Manager, error) { - tcpRuleSet, err := tcpfilters.NewRuleSet(cfg.Rules) +func NewManager(cfg *common.ProxyConfig, producer *export.ProducerClient) (*Manager, error) { + rs, err := filters.NewRuleSet(cfg.Rules) if err != nil { - logrus.Fatalf("Error creating tcp ruleset: %v", err) + return nil, fmt.Errorf("parsing rules: %w", err) } - - httpRuleSet, err := httpfilters.NewRuleSet(cfg.Rules) - if err != nil { - logrus.Fatalf("Error creating http ruleset: %v", err) + logrus.Debug("Parsed rules:") + for name, rule := range rs.Rules { + logrus.Debugf("%s -> %s", name, rule) } proxies := make([]Proxy, 0) for _, s := range cfg.Services { var p Proxy if s.Type == "tcp" { - if p, err = tcp.NewProxy(s, tcpRuleSet); err != nil { + if p, err = tcp.NewProxy(s, rs, producer); err != nil { logrus.Fatalf("Error creating tcp proxy: %v", err) } } else if s.Type == "http" { - if p, err = http.NewProxy(s, httpRuleSet); err != nil { + if p, err = http.NewProxy(s, rs, producer); err != nil { logrus.Fatalf("Error creating http proxy: %v", err) } } else { @@ -102,9 +101,9 @@ func (m Manager) DumpProxies() []models.ProxyDescription { result := make([]models.ProxyDescription, 0, len(m.proxies)) for i, p := range m.proxies { proxyID := i + 1 - filters := p.GetFilters() - descriptions := make([]models.FilterDescription, 0, len(filters)) - for j, f := range filters { + fs := p.GetFilters() + descriptions := make([]models.FilterDescription, 0, len(fs)) + for j, f := range fs { desc := models.FilterDescription{ ID: j + 1, ProxyID: proxyID, diff --git a/internal/proxy/tcp/filters/composite.go b/internal/proxy/tcp/filters/composite.go deleted file mode 100644 index fcc0e4d..0000000 --- a/internal/proxy/tcp/filters/composite.go +++ /dev/null @@ -1,77 +0,0 @@ -package filters - -import ( - "fmt" - "goxy/internal/common" - "strings" -) - -func NewCompositeAndRule(rs RuleSet, cfg common.RuleConfig) (Rule, error) { - if len(cfg.Args) < 2 { - return nil, ErrInvalidRuleArgs - } - r := CompositeAndRule{rules: make([]Rule, 0, len(cfg.Args))} - for _, name := range cfg.Args { - rule, ok := rs.GetRule(name) - if !ok { - return nil, fmt.Errorf("invalid rule name: %s", name) - } - r.rules = append(r.rules, rule) - } - return r, nil -} - -func NewCompositeNotRule(rs RuleSet, cfg common.RuleConfig) (Rule, error) { - if len(cfg.Args) != 1 { - return nil, ErrInvalidRuleArgs - } - - name := cfg.Args[0] - rule, ok := rs.GetRule(name) - if !ok { - return nil, fmt.Errorf("invalid rule name: %s", name) - } - - return CompositeNotRule{rule: rule}, nil -} - -type CompositeAndRule struct { - rules []Rule -} - -func (r CompositeAndRule) Apply(ctx *common.ProxyContext, buf []byte, ingress bool) (bool, error) { - for _, rule := range r.rules { - res, err := rule.Apply(ctx, buf, ingress) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", rule, err) - } - if !res { - return false, nil - } - } - return true, nil -} - -func (r CompositeAndRule) String() string { - ruleNames := make([]string, 0, len(r.rules)) - for _, rule := range r.rules { - ruleNames = append(ruleNames, rule.String()) - } - return fmt.Sprintf("(%s)", strings.Join(ruleNames, " and ")) -} - -type CompositeNotRule struct { - rule Rule -} - -func (r CompositeNotRule) Apply(ctx *common.ProxyContext, buf []byte, ingress bool) (bool, error) { - res, err := r.rule.Apply(ctx, buf, ingress) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", r.rule, err) - } - return !res, nil -} - -func (r CompositeNotRule) String() string { - return fmt.Sprintf("not (%s)", r.rule) -} diff --git a/internal/proxy/tcp/filters/default.go b/internal/proxy/tcp/filters/default.go deleted file mode 100644 index 3d546c6..0000000 --- a/internal/proxy/tcp/filters/default.go +++ /dev/null @@ -1,24 +0,0 @@ -package filters - -var DefaultRules = map[string]Rule{ - "ingress": IngressRule{}, - "egress": CompositeNotRule{IngressRule{}}, -} - -var DefaultRuleWrappers = map[string]RuleWrapperCreator{ - "ingress": NewIngressWrapper, - "egress": NewEgressWrapper, - "not": NewNotWrapper, -} - -var DefaultRuleCreators = map[string]RuleCreator{ - "ingress": NewIngressRule, - "regex": NewRegexRule, - "contains": NewContainsRule, - "icontains": NewIContainsRule, - "counter_gt": NewCounterGTRule, - "volgactf_flag": NewVolgaCTFRule, - - "and": NewCompositeAndRule, - "not": NewCompositeNotRule, -} diff --git a/internal/proxy/tcp/filters/rules.go b/internal/proxy/tcp/filters/rules.go deleted file mode 100644 index b45a68b..0000000 --- a/internal/proxy/tcp/filters/rules.go +++ /dev/null @@ -1,173 +0,0 @@ -package filters - -import ( - "bytes" - "errors" - "fmt" - "goxy/internal/common" - "regexp" - "strconv" - "strings" -) - -var ( - ErrInvalidRuleArgs = errors.New("invalid rule arguments") -) - -func NewIngressRule(_ RuleSet, _ common.RuleConfig) (Rule, error) { - return IngressRule{}, nil -} - -func NewRegexRule(_ RuleSet, cfg common.RuleConfig) (Rule, error) { - if len(cfg.Args) != 1 { - return nil, ErrInvalidRuleArgs - } - r, err := regexp.Compile(cfg.Args[0]) - if err != nil { - return nil, fmt.Errorf("invalid regex: %w", err) - } - return RegexRule{regex: r}, nil -} - -func NewContainsRule(_ RuleSet, cfg common.RuleConfig) (Rule, error) { - if len(cfg.Args) != 1 { - return nil, ErrInvalidRuleArgs - } - r := ContainsRule{value: []byte(cfg.Args[0])} - return r, nil -} - -func NewIContainsRule(_ RuleSet, cfg common.RuleConfig) (Rule, error) { - if len(cfg.Args) != 1 { - return nil, ErrInvalidRuleArgs - } - r := IContainsRule{value: []byte(strings.ToLower(cfg.Args[0]))} - return r, nil -} - -func NewCounterGTRule(_ RuleSet, cfg common.RuleConfig) (Rule, error) { - if len(cfg.Args) != 2 { - return nil, ErrInvalidRuleArgs - } - val, err := strconv.Atoi(cfg.Args[1]) - if err != nil { - return nil, fmt.Errorf("parsing value: %w", err) - } - r := CounterGTRule{ - key: cfg.Args[0], - value: val, - } - return r, nil -} - -func NewVolgaCTFRule(_ RuleSet, cfg common.RuleConfig) (Rule, error) { - if len(cfg.Args) != 1 { - return nil, ErrInvalidRuleArgs - } - defaultAlp := []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.") - r := VolgaModifyRule{ - alpOriginal: defaultAlp, - alpShifted: []byte(cfg.Args[0]), - } - return r, nil -} - -type IngressRule struct{} - -func (r IngressRule) Apply(_ *common.ProxyContext, _ []byte, ingress bool) (bool, error) { - return ingress, nil -} - -func (r IngressRule) String() string { - return "ingress" -} - -type RegexRule struct { - regex *regexp.Regexp -} - -func (r RegexRule) Apply(_ *common.ProxyContext, buf []byte, _ bool) (bool, error) { - return r.regex.Match(buf), nil -} - -func (r RegexRule) String() string { - return fmt.Sprintf("regex '%s'", r.regex) -} - -type VolgaModifyRule struct { - alpOriginal []byte - alpShifted []byte -} - -func findByteInSlice(buf []byte, value byte) int { - for i, elem := range buf { - if value == elem { - return i - } - } - return -1 -} - -func (r VolgaModifyRule) Apply(_ *common.ProxyContext, buf []byte, ingress bool) (bool, error) { - alpFrom := r.alpOriginal - alpTo := r.alpShifted - if ingress { - alpFrom, alpTo = alpTo, alpFrom - } - prefix := `VolgaCTF{` - suffix := `}` - VolgaCTFFlagRegex := regexp.MustCompile(prefix + `[\w-]*\.[\w-]*\.[\w-]*` + suffix) - allIndices := VolgaCTFFlagRegex.FindAllIndex(buf, -1) - for _, indices := range allIndices { - start, end := indices[0]+len(prefix), indices[1]-len(suffix) - for i := start; i < end; i++ { - alpIndex := findByteInSlice(alpFrom, buf[i]) - if alpIndex == -1 { - continue - } - buf[i] = alpTo[alpIndex] - } - } - return len(allIndices) != 0, nil -} - -func (r VolgaModifyRule) String() string { - return "VolgaCTF flag editor" -} - -type ContainsRule struct { - value []byte -} - -func (r ContainsRule) Apply(_ *common.ProxyContext, buf []byte, _ bool) (bool, error) { - return bytes.Contains(buf, r.value), nil -} - -func (r ContainsRule) String() string { - return fmt.Sprintf("contains '%s'", string(r.value)) -} - -type IContainsRule struct { - value []byte -} - -func (r IContainsRule) Apply(_ *common.ProxyContext, buf []byte, _ bool) (bool, error) { - return bytes.Contains(bytes.ToLower(buf), r.value), nil -} - -func (r IContainsRule) String() string { - return fmt.Sprintf("icontains '%s'", string(r.value)) -} - -type CounterGTRule struct { - key string - value int -} - -func (r CounterGTRule) Apply(ctx *common.ProxyContext, _ []byte, _ bool) (bool, error) { - return ctx.GetCounter(r.key) > r.value, nil -} - -func (r CounterGTRule) String() string { - return fmt.Sprintf("counter '%s' > %d", r.key, r.value) -} diff --git a/internal/proxy/tcp/filters/rules_test.go b/internal/proxy/tcp/filters/rules_test.go deleted file mode 100644 index 763502d..0000000 --- a/internal/proxy/tcp/filters/rules_test.go +++ /dev/null @@ -1,264 +0,0 @@ -package filters - -import ( - "goxy/internal/common" - "regexp" - "testing" -) - -func TestContainsRule_Apply(t *testing.T) { - type fields struct { - value []byte - } - tests := []struct { - name string - fields fields - data []byte - want bool - }{ - { - "simple_contains", - fields{[]byte("test")}, - []byte("some test data"), - true, - }, - { - "simple_not_contains", - fields{[]byte("test")}, - []byte("some tst data"), - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - r := &ContainsRule{ - value: tt.fields.value, - } - got, err := r.Apply(common.NewProxyContext(), tt.data, false) - if err != nil { - t.Errorf("Apply() error = %v", err) - return - } - if got != tt.want { - t.Errorf("Apply() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestCounterGTRule_Apply(t *testing.T) { - type fields struct { - Key string - Value int - } - type contextFields struct { - Key string - Value int - } - tests := []struct { - name string - fields fields - data []byte - contextFields contextFields - want bool - }{ - { - "uninitialized false", - fields{ - "key", - 0, - }, - []byte("anything"), - contextFields{ - Key: "", - Value: 0, - }, - false, - }, - { - "uninitialized true", - fields{ - "key", - -1, - }, - []byte("anything"), - contextFields{ - Key: "", - Value: 0, - }, - true, - }, - { - "simple true", - fields{ - "key", - 0, - }, - []byte("anything"), - contextFields{ - Key: "key", - Value: 1, - }, - true, - }, - { - "simple false", - fields{ - "key", - 5, - }, - []byte("anything"), - contextFields{ - Key: "key", - Value: 5, - }, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - ctx := common.NewProxyContext() - if tt.contextFields.Key != "" { - ctx.AddToCounter(tt.contextFields.Key, tt.contextFields.Value) - } - r := &CounterGTRule{ - key: tt.fields.Key, - value: tt.fields.Value, - } - got, err := r.Apply(ctx, tt.data, false) - if err != nil { - t.Errorf("Apply() error = %v", err) - return - } - if got != tt.want { - t.Errorf("Apply() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestIngressRule_Apply(t *testing.T) { - tests := []struct { - name string - ingress bool - data []byte - }{ - { - "empty ingress", - true, - []byte(""), - }, - { - "empty egress", - false, - []byte(""), - }, - { - "ingress with data", - true, - []byte("some data"), - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - r := &IngressRule{} - got, err := r.Apply(common.NewProxyContext(), tt.data, tt.ingress) - if err != nil { - t.Errorf("Apply() error = %v", err) - return - } - if got != tt.ingress { - t.Errorf("Apply() got = %v, want %v", got, tt.ingress) - } - }) - } -} - -func TestRegexRule_Apply(t *testing.T) { - tests := []struct { - name string - Regex *regexp.Regexp - data []byte - want bool - }{ - { - "simple_contains", - regexp.MustCompile("test"), - []byte("some test data"), - true, - }, - { - "simple_not_contains", - regexp.MustCompile("test"), - []byte("some tst data"), - false, - }, - { - "full match", - regexp.MustCompile("^[A-Z0-9]{5}=$"), - []byte("ABCZ7="), - true, - }, - { - "flag urlencode", - regexp.MustCompile("[A-Z0-9]{5}(=|%3d|%3D)"), - []byte("ABCZ7%3d"), - true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - r := &RegexRule{ - regex: tt.Regex, - } - got, err := r.Apply(common.NewProxyContext(), tt.data, false) - if err != nil { - t.Errorf("Apply() error = %v", err) - return - } - if got != tt.want { - t.Errorf("Apply() got = %v, want %v", got, tt.want) - } - }) - } -} - -func TestIContainsRule_Apply(t *testing.T) { - type fields struct { - value []byte - } - tests := []struct { - name string - fields fields - data []byte - want bool - }{ - { - "simple_contains", - fields{[]byte("test")}, - []byte("some tEsT data"), - true, - }, - { - "simple_not_contains", - fields{[]byte("test")}, - []byte("some tst data"), - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - r := &IContainsRule{ - value: tt.fields.value, - } - got, err := r.Apply(common.NewProxyContext(), tt.data, false) - if err != nil { - t.Errorf("Apply() error = %v", err) - return - } - if got != tt.want { - t.Errorf("Apply() got = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/internal/proxy/tcp/filters/ruleset.go b/internal/proxy/tcp/filters/ruleset.go deleted file mode 100644 index eb51bf5..0000000 --- a/internal/proxy/tcp/filters/ruleset.go +++ /dev/null @@ -1,60 +0,0 @@ -package filters - -import ( - "fmt" - "goxy/internal/common" - "strings" -) - -type RuleSet struct { - Rules map[string]Rule -} - -func (rs RuleSet) GetRule(name string) (Rule, bool) { - if rule, ok := rs.Rules[name]; ok { - return rule, true - } - if rule, ok := DefaultRules[name]; ok { - return rule, true - } - return nil, false -} - -func NewRuleSet(cfg []common.RuleConfig) (*RuleSet, error) { - rs := RuleSet{Rules: make(map[string]Rule)} - - for _, rc := range cfg { - if strings.HasPrefix(rc.Type, "tcp::") { - tokens := strings.Split(rc.Type, "::") - if len(tokens) < 2 { - return nil, fmt.Errorf("invalid rule: %s", rc.Type) - } - - // the last rule in chain must be either the composite rule or some rule creator - lastToken := tokens[len(tokens)-1] - - var rule Rule - var err error - if creator, ok := DefaultRuleCreators[lastToken]; ok { - if rule, err = creator(rs, rc); err != nil { - return nil, fmt.Errorf("creating rule %s: %w", lastToken, err) - } - } else { - return nil, fmt.Errorf("invalid rule %s: last token invalid", rc.Type) - } - - for i := len(tokens) - 2; i > 0; i -= 1 { - wrapperName := tokens[i] - wrapper, ok := DefaultRuleWrappers[wrapperName] - if !ok { - return nil, fmt.Errorf("invalid wrapper name: %s", wrapperName) - } - rule = wrapper(rule, rc) - } - - rs.Rules[rc.Name] = rule - } - } - - return &rs, nil -} diff --git a/internal/proxy/tcp/filters/wrappers.go b/internal/proxy/tcp/filters/wrappers.go deleted file mode 100644 index fad3a64..0000000 --- a/internal/proxy/tcp/filters/wrappers.go +++ /dev/null @@ -1,72 +0,0 @@ -package filters - -import ( - "fmt" - "goxy/internal/common" -) - -func NewIngressWrapper(rule Rule, _ common.RuleConfig) Rule { - return &IngressWrapper{rule} -} - -func NewEgressWrapper(rule Rule, _ common.RuleConfig) Rule { - return &EgressWrapper{rule} -} - -func NewNotWrapper(rule Rule, _ common.RuleConfig) Rule { - return &NotWrapper{rule} -} - -type IngressWrapper struct { - rule Rule -} - -func (w IngressWrapper) Apply(ctx *common.ProxyContext, buf []byte, ingress bool) (bool, error) { - if !ingress { - return false, nil - } - res, err := w.rule.Apply(ctx, buf, ingress) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", w.rule, err) - } - return res, nil -} - -func (w IngressWrapper) String() string { - return fmt.Sprintf("ingress and %s", w.rule) -} - -type EgressWrapper struct { - rule Rule -} - -func (w EgressWrapper) Apply(ctx *common.ProxyContext, buf []byte, ingress bool) (bool, error) { - if ingress { - return false, nil - } - res, err := w.rule.Apply(ctx, buf, ingress) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", w.rule, err) - } - return res, nil -} - -func (w EgressWrapper) String() string { - return fmt.Sprintf("egress and %s", w.rule) -} - -type NotWrapper struct { - rule Rule -} - -func (w NotWrapper) Apply(ctx *common.ProxyContext, buf []byte, ingress bool) (bool, error) { - res, err := w.rule.Apply(ctx, buf, ingress) - if err != nil { - return false, fmt.Errorf("error in rule %T: %w", w.rule, err) - } - return !res, nil -} - -func (w NotWrapper) String() string { - return fmt.Sprintf("not (%s)", w.rule) -} diff --git a/internal/proxy/tcp/filters/wrappers_test.go b/internal/proxy/tcp/filters/wrappers_test.go deleted file mode 100644 index 9fb9d99..0000000 --- a/internal/proxy/tcp/filters/wrappers_test.go +++ /dev/null @@ -1,133 +0,0 @@ -package filters - -import ( - "goxy/internal/common" - "testing" -) - -type trueRule struct { - calls int -} - -func (r *trueRule) Apply(_ *common.ProxyContext, _ []byte, _ bool) (bool, error) { - r.calls += 1 - return true, nil -} - -func (r trueRule) String() string { - return "true" -} - -func TestEgressWrapper_Apply(t *testing.T) { - tests := []struct { - name string - rule *trueRule - ingress bool - want bool - }{ - { - "ingress packet", - &trueRule{}, - true, - false, - }, - { - "egress packet", - &trueRule{}, - false, - true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - w := &EgressWrapper{ - rule: tt.rule, - } - got, err := w.Apply(common.NewProxyContext(), nil, tt.ingress) - if err != nil { - t.Errorf("Apply() error = %v", err) - return - } - if got != tt.want { - t.Errorf("Apply() got = %v, want %v", got, tt.want) - } - if !got && tt.rule.calls > 0 { - t.Errorf("Apply() inner rule called, but mustn't be") - } - }) - } -} - -func TestIngressWrapper_Apply(t *testing.T) { - tests := []struct { - name string - rule *trueRule - ingress bool - want bool - }{ - { - "ingress packet", - &trueRule{}, - true, - true, - }, - { - "egress packet", - &trueRule{}, - false, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - w := &IngressWrapper{ - rule: tt.rule, - } - got, err := w.Apply(common.NewProxyContext(), nil, tt.ingress) - if err != nil { - t.Errorf("Apply() error = %v", err) - return - } - if got != tt.want { - t.Errorf("Apply() got = %v, want %v", got, tt.want) - } - if !got && tt.rule.calls > 0 { - t.Errorf("Apply() inner rule called, but mustn't be") - } - }) - } -} - -func TestNotWrapper_Apply(t *testing.T) { - tests := []struct { - name string - rule *trueRule - ingress bool - want bool - }{ - { - "true packet", - &trueRule{}, - true, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - w := &NotWrapper{ - rule: tt.rule, - } - got, err := w.Apply(common.NewProxyContext(), nil, tt.ingress) - if err != nil { - t.Errorf("Apply() error = %v", err) - return - } - if got != tt.want { - t.Errorf("Apply() got = %v, want %v", got, tt.want) - } - if tt.rule.calls == 0 { - t.Errorf("Apply() inner rule not called, but must be") - } - }) - } -} diff --git a/internal/proxy/tcp/proxy.go b/internal/proxy/tcp/proxy.go index 15229ab..64eee2d 100644 --- a/internal/proxy/tcp/proxy.go +++ b/internal/proxy/tcp/proxy.go @@ -4,12 +4,19 @@ import ( "context" "errors" "fmt" - "go.uber.org/atomic" - "goxy/internal/common" - "goxy/internal/proxy/tcp/filters" "io" "net" + "strconv" "sync" + "time" + + "github.com/google/uuid" + "go.uber.org/atomic" + + "goxy/internal/common" + "goxy/internal/export" + "goxy/internal/filters" + "goxy/internal/wrapper" "github.com/sirupsen/logrus" ) @@ -22,7 +29,7 @@ var ( ErrInvalidFilter = errors.New("no such filter") ) -func NewProxy(cfg common.ServiceConfig, rs *filters.RuleSet) (*Proxy, error) { +func NewProxy(cfg common.ServiceConfig, rs *filters.RuleSet, pc *export.ProducerClient) (*Proxy, error) { fts := make([]filters.Filter, 0, len(cfg.Filters)) for _, f := range cfg.Filters { rule, ok := rs.GetRule(f.Rule) @@ -45,12 +52,14 @@ func NewProxy(cfg common.ServiceConfig, rs *filters.RuleSet) (*Proxy, error) { p := &Proxy{ ListenAddr: cfg.Listen, TargetAddr: cfg.Target, + Name: cfg.Name, serviceConfig: cfg, logger: logger, filters: fts, conns: newConnMap(), wg: new(sync.WaitGroup), + producer: pc, } return p, nil } @@ -58,6 +67,7 @@ func NewProxy(cfg common.ServiceConfig, rs *filters.RuleSet) (*Proxy, error) { type Proxy struct { ListenAddr string TargetAddr string + Name string serviceConfig common.ServiceConfig closing bool @@ -68,6 +78,7 @@ type Proxy struct { listener net.Listener logger *logrus.Entry filters []filters.Filter + producer *export.ProducerClient } func (p Proxy) GetListening() bool { @@ -132,7 +143,11 @@ func (p Proxy) runFilters(pctx *common.ProxyContext, buf []byte, ingress bool) e if !f.IsEnabled() { continue } - res, err := f.Rule.Apply(pctx, buf, ingress) + entity := wrapper.Packet{ + Content: buf, + Ingress: ingress, + } + res, err := f.Rule.Apply(pctx, entity) if err != nil { return fmt.Errorf("error in rule %T: %w", f.Rule, err) } @@ -164,7 +179,7 @@ func (p Proxy) GetFilters() []common.Filter { return result } -func (p Proxy) oneSideHandler(conn *Connection, logger *logrus.Entry, ingress bool) error { +func (p Proxy) oneSideHandler(conn *Connection, logger *logrus.Entry, ingress bool, base *export.BasePacket) error { var ( src io.Reader dst io.Writer @@ -183,6 +198,7 @@ func (p Proxy) oneSideHandler(conn *Connection, logger *logrus.Entry, ingress bo if nr > 0 { data := buf[:nr] + p.exportBuf(context.Background(), data, ingress, base, logger) if err := p.runFilters(conn.Context, data, ingress); err != nil { logger.Errorf("Error running filters: %v", err) @@ -213,6 +229,24 @@ func (p Proxy) oneSideHandler(conn *Connection, logger *logrus.Entry, ingress bo return nil } +func (p *Proxy) exportBuf(ctx context.Context, buf []byte, ingress bool, base *export.BasePacket, logger *logrus.Entry) { + if p.producer == nil { + logger.Debug("Exporter is disabled") + return + } + reqPacket := export.Packet{ + BasePacket: base, + Content: buf, + CaptureTime: time.Now(), + FilterData: 0, // TODO: add filters. + Inbound: ingress, + Reversed: !ingress, + } + if err := p.producer.Send(ctx, &reqPacket); err != nil { + logger.Warningf("Error sending to producer: %v", err) + } +} + func (p Proxy) handleConnection(id string) { defer p.wg.Done() @@ -225,6 +259,8 @@ func (p Proxy) handleConnection(id string) { p.conns.remove(id) }() + base := p.getBasePacket(conn) + connLogger.Debugf("Connection received") localConn, err := net.Dial("tcp", p.TargetAddr) if err != nil { @@ -244,7 +280,7 @@ func (p Proxy) handleConnection(id string) { } logger.Debug("Counterpart connection closed") }() - if err := p.oneSideHandler(c, logger, ingress); err != nil { + if err := p.oneSideHandler(c, logger, ingress, base); err != nil { if !isConnectionClosedErr(err) { logger.Errorf("Error in connection: %v", err) } else { @@ -260,6 +296,23 @@ func (p Proxy) handleConnection(id string) { wg.Wait() } +func (p *Proxy) getBasePacket(conn net.Conn) *export.BasePacket { + srcHost, srcPort := splitAddrSafe(conn.RemoteAddr().String(), 0) + dstHost, dstPort := splitAddrSafe(conn.LocalAddr().String(), 0) + + return &export.BasePacket{ + Source: fmt.Sprintf("goxy-%s", p.Name), + Endpoints: &export.EndpointData{ + IPSrc: srcHost, + IPDst: dstHost, + PortSrc: srcPort, + PortDst: dstPort, + }, + Proto: "tcp", + ProducerStreamID: uuid.New().String(), + } +} + func (p *Proxy) serve() { defer p.wg.Done() @@ -290,3 +343,16 @@ func (p *Proxy) serve() { go p.handleConnection(connID) } } + +func splitAddrSafe(addr string, defPort int) (host string, port int) { + host, portStr, err := net.SplitHostPort(addr) + if err != nil { + host = "0.0.0.0" + port = defPort + } else { + if port, err = strconv.Atoi(portStr); err != nil { + port = defPort + } + } + return host, port +} diff --git a/internal/proxy/http/wrapper/interface.go b/internal/wrapper/interface.go similarity index 51% rename from internal/proxy/http/wrapper/interface.go rename to internal/wrapper/interface.go index 91a5ec1..534f675 100644 --- a/internal/proxy/http/wrapper/interface.go +++ b/internal/wrapper/interface.go @@ -1,19 +1,26 @@ package wrapper import ( + "errors" "net/http" "net/url" ) +var ( + ErrNotSupported = errors.New("not supported") +) + type Entity interface { GetIngress() bool - GetCookies() []*http.Cookie - GetHeaders() map[string][]string - GetURL() *url.URL + GetCookies() ([]*http.Cookie, error) + GetHeaders() (map[string][]string, error) + GetURL() (*url.URL, error) GetBody() ([]byte, error) GetJSON() (interface{}, error) GetForm() (map[string][]string, error) + GetRaw() ([]byte, error) + SetBody([]byte) } diff --git a/internal/wrapper/packet.go b/internal/wrapper/packet.go new file mode 100644 index 0000000..aa774ea --- /dev/null +++ b/internal/wrapper/packet.go @@ -0,0 +1,57 @@ +package wrapper + +import ( + "encoding/json" + "fmt" + "net/http" + "net/url" +) + +// Packet is a wrapper around raw data (e.g. tcp packet) implementing Entity interface. +type Packet struct { + Content []byte + Ingress bool +} + +func (p Packet) GetForm() (map[string][]string, error) { + return nil, ErrNotSupported +} + +func (p Packet) GetJSON() (interface{}, error) { + result := new(interface{}) + if err := json.Unmarshal(p.Content, result); err != nil { + return nil, fmt.Errorf("parsing json: %w", err) + } + return *result, nil +} + +func (p Packet) GetBody() ([]byte, error) { + dst := make([]byte, len(p.Content)) + copy(dst, p.Content) + return dst, nil +} + +func (p Packet) GetIngress() bool { + return p.Ingress +} + +func (p Packet) GetCookies() ([]*http.Cookie, error) { + return nil, ErrNotSupported +} + +func (p Packet) GetHeaders() (map[string][]string, error) { + return nil, ErrNotSupported +} + +func (p Packet) GetURL() (*url.URL, error) { + return nil, ErrNotSupported +} + +func (p Packet) GetRaw() ([]byte, error) { + return p.Content, nil +} + +func (p Packet) SetBody(data []byte) { + p.Content = make([]byte, len(data)) + copy(p.Content, data) +} diff --git a/internal/proxy/http/wrapper/reader.go b/internal/wrapper/reader.go similarity index 100% rename from internal/proxy/http/wrapper/reader.go rename to internal/wrapper/reader.go diff --git a/internal/proxy/http/wrapper/request.go b/internal/wrapper/request.go similarity index 72% rename from internal/proxy/http/wrapper/request.go rename to internal/wrapper/request.go index c71ee3b..09b9d4f 100644 --- a/internal/proxy/http/wrapper/request.go +++ b/internal/wrapper/request.go @@ -3,10 +3,12 @@ package wrapper import ( "encoding/json" "fmt" - "github.com/sirupsen/logrus" "io/ioutil" "net/http" + "net/http/httputil" "net/url" + + "github.com/sirupsen/logrus" ) // Request is a wrapper around http.Request implementing Entity interface. @@ -46,16 +48,16 @@ func (r Request) GetIngress() bool { return true } -func (r Request) GetCookies() []*http.Cookie { - return r.Request.Cookies() +func (r Request) GetCookies() ([]*http.Cookie, error) { + return r.Request.Cookies(), nil } -func (r Request) GetHeaders() map[string][]string { - return r.Request.Header +func (r Request) GetHeaders() (map[string][]string, error) { + return r.Request.Header, nil } -func (r Request) GetURL() *url.URL { - return r.Request.URL +func (r Request) GetURL() (*url.URL, error) { + return r.Request.URL, nil } func (r Request) SetBody(data []byte) { @@ -63,6 +65,15 @@ func (r Request) SetBody(data []byte) { r.Request.Body = NewBodyReaderFromRaw(data) } +func (r Request) GetRaw() ([]byte, error) { + defer r.resetBody() + data, err := httputil.DumpRequest(r.Request, true) + if err != nil { + return nil, fmt.Errorf("dumping request: %w", err) + } + return data, err +} + func (r Request) resetBody() { if err := r.Request.Body.Close(); err != nil { logrus.Errorf("Error resetting request body: %v", err) diff --git a/internal/proxy/http/wrapper/response.go b/internal/wrapper/response.go similarity index 70% rename from internal/proxy/http/wrapper/response.go rename to internal/wrapper/response.go index 14a2f3a..a395e90 100644 --- a/internal/proxy/http/wrapper/response.go +++ b/internal/wrapper/response.go @@ -3,10 +3,12 @@ package wrapper import ( "encoding/json" "fmt" - "github.com/sirupsen/logrus" "io/ioutil" "net/http" + "net/http/httputil" "net/url" + + "github.com/sirupsen/logrus" ) // Response is a wrapper around http.Response implementing Entity interface. @@ -43,19 +45,28 @@ func (r Response) GetBody() ([]byte, error) { return buf, nil } -func (r Response) GetCookies() []*http.Cookie { - return r.Response.Cookies() +func (r Response) GetCookies() ([]*http.Cookie, error) { + return r.Response.Cookies(), nil } -func (r Response) GetHeaders() map[string][]string { - return r.Response.Header +func (r Response) GetHeaders() (map[string][]string, error) { + return r.Response.Header, nil } -func (r Response) GetURL() *url.URL { +func (r Response) GetURL() (*url.URL, error) { if r.Response.Request != nil { - return r.Response.Request.URL + return r.Response.Request.URL, nil + } + return nil, nil +} + +func (r Response) GetRaw() ([]byte, error) { + defer r.resetBody() + data, err := httputil.DumpResponse(r.Response, true) + if err != nil { + return nil, fmt.Errorf("dumping request: %w", err) } - return nil + return data, err } func (r Response) SetBody(data []byte) { diff --git a/lib/mongol/mongol.pb.go b/lib/mongol/mongol.pb.go new file mode 100644 index 0000000..12de67d --- /dev/null +++ b/lib/mongol/mongol.pb.go @@ -0,0 +1,1123 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.17.3 +// source: mongol.proto + +package MonGol + +import ( + "reflect" + "sync" + + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/runtime/protoimpl" + "google.golang.org/protobuf/types/known/timestamppb" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type EndpointData struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + IpSrc string `protobuf:"bytes,1,opt,name=ip_src,json=ipSrc,proto3" json:"ip_src,omitempty"` + IpDst string `protobuf:"bytes,2,opt,name=ip_dst,json=ipDst,proto3" json:"ip_dst,omitempty"` + PortSrc int32 `protobuf:"varint,3,opt,name=port_src,json=portSrc,proto3" json:"port_src,omitempty"` + PortDst int32 `protobuf:"varint,4,opt,name=port_dst,json=portDst,proto3" json:"port_dst,omitempty"` +} + +func (x *EndpointData) Reset() { + *x = EndpointData{} + if protoimpl.UnsafeEnabled { + mi := &file_mongol_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EndpointData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EndpointData) ProtoMessage() {} + +func (x *EndpointData) ProtoReflect() protoreflect.Message { + mi := &file_mongol_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EndpointData.ProtoReflect.Descriptor instead. +func (*EndpointData) Descriptor() ([]byte, []int) { + return file_mongol_proto_rawDescGZIP(), []int{0} +} + +func (x *EndpointData) GetIpSrc() string { + if x != nil { + return x.IpSrc + } + return "" +} + +func (x *EndpointData) GetIpDst() string { + if x != nil { + return x.IpDst + } + return "" +} + +func (x *EndpointData) GetPortSrc() int32 { + if x != nil { + return x.PortSrc + } + return 0 +} + +func (x *EndpointData) GetPortDst() int32 { + if x != nil { + return x.PortDst + } + return 0 +} + +type CaptureConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` + Port int32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` + KeyFile string `protobuf:"bytes,3,opt,name=key_file,json=keyFile,proto3" json:"key_file,omitempty"` + Password string `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"` + Iface string `protobuf:"bytes,5,opt,name=iface,proto3" json:"iface,omitempty"` + Disabled bool `protobuf:"varint,6,opt,name=disabled,proto3" json:"disabled,omitempty"` +} + +func (x *CaptureConfig) Reset() { + *x = CaptureConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_mongol_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CaptureConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CaptureConfig) ProtoMessage() {} + +func (x *CaptureConfig) ProtoReflect() protoreflect.Message { + mi := &file_mongol_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CaptureConfig.ProtoReflect.Descriptor instead. +func (*CaptureConfig) Descriptor() ([]byte, []int) { + return file_mongol_proto_rawDescGZIP(), []int{1} +} + +func (x *CaptureConfig) GetHost() string { + if x != nil { + return x.Host + } + return "" +} + +func (x *CaptureConfig) GetPort() int32 { + if x != nil { + return x.Port + } + return 0 +} + +func (x *CaptureConfig) GetKeyFile() string { + if x != nil { + return x.KeyFile + } + return "" +} + +func (x *CaptureConfig) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +func (x *CaptureConfig) GetIface() string { + if x != nil { + return x.Iface + } + return "" +} + +func (x *CaptureConfig) GetDisabled() bool { + if x != nil { + return x.Disabled + } + return false +} + +type Service struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Proto string `protobuf:"bytes,3,opt,name=proto,proto3" json:"proto,omitempty"` + Port int32 `protobuf:"varint,4,opt,name=port,proto3" json:"port,omitempty"` + IsHttp bool `protobuf:"varint,5,opt,name=is_http,json=isHttp,proto3" json:"is_http,omitempty"` + Capture *CaptureConfig `protobuf:"bytes,6,opt,name=capture,proto3" json:"capture,omitempty"` +} + +func (x *Service) Reset() { + *x = Service{} + if protoimpl.UnsafeEnabled { + mi := &file_mongol_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Service) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Service) ProtoMessage() {} + +func (x *Service) ProtoReflect() protoreflect.Message { + mi := &file_mongol_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Service.ProtoReflect.Descriptor instead. +func (*Service) Descriptor() ([]byte, []int) { + return file_mongol_proto_rawDescGZIP(), []int{2} +} + +func (x *Service) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *Service) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Service) GetProto() string { + if x != nil { + return x.Proto + } + return "" +} + +func (x *Service) GetPort() int32 { + if x != nil { + return x.Port + } + return 0 +} + +func (x *Service) GetIsHttp() bool { + if x != nil { + return x.IsHttp + } + return false +} + +func (x *Service) GetCapture() *CaptureConfig { + if x != nil { + return x.Capture + } + return nil +} + +type Packet struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + StreamId int32 `protobuf:"varint,2,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + Source string `protobuf:"bytes,3,opt,name=source,proto3" json:"source,omitempty"` + Inbound bool `protobuf:"varint,4,opt,name=inbound,proto3" json:"inbound,omitempty"` + Reversed bool `protobuf:"varint,5,opt,name=reversed,proto3" json:"reversed,omitempty"` + Endpoints *EndpointData `protobuf:"bytes,6,opt,name=endpoints,proto3" json:"endpoints,omitempty"` + Proto string `protobuf:"bytes,7,opt,name=proto,proto3" json:"proto,omitempty"` + Content []byte `protobuf:"bytes,8,opt,name=content,proto3" json:"content,omitempty"` + ServiceId int32 `protobuf:"varint,9,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` + CaptureTime *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=capture_time,json=captureTime,proto3" json:"capture_time,omitempty"` + FilterData uint64 `protobuf:"varint,11,opt,name=filter_data,json=filterData,proto3" json:"filter_data,omitempty"` + ProducerStreamId string `protobuf:"bytes,12,opt,name=producer_stream_id,json=producerStreamId,proto3" json:"producer_stream_id,omitempty"` +} + +func (x *Packet) Reset() { + *x = Packet{} + if protoimpl.UnsafeEnabled { + mi := &file_mongol_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Packet) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Packet) ProtoMessage() {} + +func (x *Packet) ProtoReflect() protoreflect.Message { + mi := &file_mongol_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Packet.ProtoReflect.Descriptor instead. +func (*Packet) Descriptor() ([]byte, []int) { + return file_mongol_proto_rawDescGZIP(), []int{3} +} + +func (x *Packet) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *Packet) GetStreamId() int32 { + if x != nil { + return x.StreamId + } + return 0 +} + +func (x *Packet) GetSource() string { + if x != nil { + return x.Source + } + return "" +} + +func (x *Packet) GetInbound() bool { + if x != nil { + return x.Inbound + } + return false +} + +func (x *Packet) GetReversed() bool { + if x != nil { + return x.Reversed + } + return false +} + +func (x *Packet) GetEndpoints() *EndpointData { + if x != nil { + return x.Endpoints + } + return nil +} + +func (x *Packet) GetProto() string { + if x != nil { + return x.Proto + } + return "" +} + +func (x *Packet) GetContent() []byte { + if x != nil { + return x.Content + } + return nil +} + +func (x *Packet) GetServiceId() int32 { + if x != nil { + return x.ServiceId + } + return 0 +} + +func (x *Packet) GetCaptureTime() *timestamppb.Timestamp { + if x != nil { + return x.CaptureTime + } + return nil +} + +func (x *Packet) GetFilterData() uint64 { + if x != nil { + return x.FilterData + } + return 0 +} + +func (x *Packet) GetProducerStreamId() string { + if x != nil { + return x.ProducerStreamId + } + return "" +} + +type Filter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Code uint32 `protobuf:"varint,2,opt,name=code,proto3" json:"code,omitempty"` +} + +func (x *Filter) Reset() { + *x = Filter{} + if protoimpl.UnsafeEnabled { + mi := &file_mongol_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Filter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Filter) ProtoMessage() {} + +func (x *Filter) ProtoReflect() protoreflect.Message { + mi := &file_mongol_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Filter.ProtoReflect.Descriptor instead. +func (*Filter) Descriptor() ([]byte, []int) { + return file_mongol_proto_rawDescGZIP(), []int{4} +} + +func (x *Filter) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Filter) GetCode() uint32 { + if x != nil { + return x.Code + } + return 0 +} + +type Config struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FlagRegex string `protobuf:"bytes,1,opt,name=flag_regex,json=flagRegex,proto3" json:"flag_regex,omitempty"` + HostRegex string `protobuf:"bytes,2,opt,name=host_regex,json=hostRegex,proto3" json:"host_regex,omitempty"` + Services []*Service `protobuf:"bytes,3,rep,name=services,proto3" json:"services,omitempty"` + TcpdumpCommands []string `protobuf:"bytes,4,rep,name=tcpdump_commands,json=tcpdumpCommands,proto3" json:"tcpdump_commands,omitempty"` +} + +func (x *Config) Reset() { + *x = Config{} + if protoimpl.UnsafeEnabled { + mi := &file_mongol_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Config) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Config) ProtoMessage() {} + +func (x *Config) ProtoReflect() protoreflect.Message { + mi := &file_mongol_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Config.ProtoReflect.Descriptor instead. +func (*Config) Descriptor() ([]byte, []int) { + return file_mongol_proto_rawDescGZIP(), []int{5} +} + +func (x *Config) GetFlagRegex() string { + if x != nil { + return x.FlagRegex + } + return "" +} + +func (x *Config) GetHostRegex() string { + if x != nil { + return x.HostRegex + } + return "" +} + +func (x *Config) GetServices() []*Service { + if x != nil { + return x.Services + } + return nil +} + +func (x *Config) GetTcpdumpCommands() []string { + if x != nil { + return x.TcpdumpCommands + } + return nil +} + +type AddPacketRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Packet *Packet `protobuf:"bytes,1,opt,name=packet,proto3" json:"packet,omitempty"` +} + +func (x *AddPacketRequest) Reset() { + *x = AddPacketRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_mongol_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPacketRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPacketRequest) ProtoMessage() {} + +func (x *AddPacketRequest) ProtoReflect() protoreflect.Message { + mi := &file_mongol_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddPacketRequest.ProtoReflect.Descriptor instead. +func (*AddPacketRequest) Descriptor() ([]byte, []int) { + return file_mongol_proto_rawDescGZIP(), []int{6} +} + +func (x *AddPacketRequest) GetPacket() *Packet { + if x != nil { + return x.Packet + } + return nil +} + +type AddPacketResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *AddPacketResponse) Reset() { + *x = AddPacketResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_mongol_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AddPacketResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AddPacketResponse) ProtoMessage() {} + +func (x *AddPacketResponse) ProtoReflect() protoreflect.Message { + mi := &file_mongol_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AddPacketResponse.ProtoReflect.Descriptor instead. +func (*AddPacketResponse) Descriptor() ([]byte, []int) { + return file_mongol_proto_rawDescGZIP(), []int{7} +} + +type RegisterFiltersRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Names []string `protobuf:"bytes,1,rep,name=names,proto3" json:"names,omitempty"` +} + +func (x *RegisterFiltersRequest) Reset() { + *x = RegisterFiltersRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_mongol_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegisterFiltersRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterFiltersRequest) ProtoMessage() {} + +func (x *RegisterFiltersRequest) ProtoReflect() protoreflect.Message { + mi := &file_mongol_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterFiltersRequest.ProtoReflect.Descriptor instead. +func (*RegisterFiltersRequest) Descriptor() ([]byte, []int) { + return file_mongol_proto_rawDescGZIP(), []int{8} +} + +func (x *RegisterFiltersRequest) GetNames() []string { + if x != nil { + return x.Names + } + return nil +} + +type RegisterFiltersResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Filters []*Filter `protobuf:"bytes,1,rep,name=filters,proto3" json:"filters,omitempty"` +} + +func (x *RegisterFiltersResponse) Reset() { + *x = RegisterFiltersResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_mongol_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RegisterFiltersResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RegisterFiltersResponse) ProtoMessage() {} + +func (x *RegisterFiltersResponse) ProtoReflect() protoreflect.Message { + mi := &file_mongol_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RegisterFiltersResponse.ProtoReflect.Descriptor instead. +func (*RegisterFiltersResponse) Descriptor() ([]byte, []int) { + return file_mongol_proto_rawDescGZIP(), []int{9} +} + +func (x *RegisterFiltersResponse) GetFilters() []*Filter { + if x != nil { + return x.Filters + } + return nil +} + +type GetConfigRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetConfigRequest) Reset() { + *x = GetConfigRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_mongol_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetConfigRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetConfigRequest) ProtoMessage() {} + +func (x *GetConfigRequest) ProtoReflect() protoreflect.Message { + mi := &file_mongol_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetConfigRequest.ProtoReflect.Descriptor instead. +func (*GetConfigRequest) Descriptor() ([]byte, []int) { + return file_mongol_proto_rawDescGZIP(), []int{10} +} + +type GetConfigResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Config *Config `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` +} + +func (x *GetConfigResponse) Reset() { + *x = GetConfigResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_mongol_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetConfigResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetConfigResponse) ProtoMessage() {} + +func (x *GetConfigResponse) ProtoReflect() protoreflect.Message { + mi := &file_mongol_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetConfigResponse.ProtoReflect.Descriptor instead. +func (*GetConfigResponse) Descriptor() ([]byte, []int) { + return file_mongol_proto_rawDescGZIP(), []int{11} +} + +func (x *GetConfigResponse) GetConfig() *Config { + if x != nil { + return x.Config + } + return nil +} + +var File_mongol_proto protoreflect.FileDescriptor + +var file_mongol_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, + 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x72, 0x0a, 0x0c, 0x45, 0x6e, 0x64, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x70, 0x5f, 0x73, 0x72, + 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x70, 0x53, 0x72, 0x63, 0x12, 0x15, + 0x0a, 0x06, 0x69, 0x70, 0x5f, 0x64, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x69, 0x70, 0x44, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x72, + 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x72, 0x63, + 0x12, 0x19, 0x0a, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x64, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x07, 0x70, 0x6f, 0x72, 0x74, 0x44, 0x73, 0x74, 0x22, 0xa0, 0x01, 0x0a, 0x0d, + 0x43, 0x61, 0x70, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, + 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, + 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x69, 0x6c, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x46, 0x69, 0x6c, 0x65, + 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x14, 0x0a, 0x05, + 0x69, 0x66, 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x66, 0x61, + 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xa1, + 0x01, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, + 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x68, + 0x74, 0x74, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x48, 0x74, 0x74, + 0x70, 0x12, 0x2f, 0x0a, 0x07, 0x63, 0x61, 0x70, 0x74, 0x75, 0x72, 0x65, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x2e, 0x43, 0x61, 0x70, 0x74, + 0x75, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x63, 0x61, 0x70, 0x74, 0x75, + 0x72, 0x65, 0x22, 0x94, 0x03, 0x0a, 0x06, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, + 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x1a, 0x0a, 0x08, + 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, + 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x6f, + 0x6e, 0x67, 0x6f, 0x6c, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x44, 0x61, 0x74, + 0x61, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x3d, 0x0a, 0x0c, 0x63, + 0x61, 0x70, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x63, + 0x61, 0x70, 0x74, 0x75, 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x0a, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x12, 0x70, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, + 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, + 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x22, 0x30, 0x0a, 0x06, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x9e, 0x01, 0x0a, 0x06, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x72, + 0x65, 0x67, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x6c, 0x61, 0x67, + 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x1d, 0x0a, 0x0a, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x72, 0x65, + 0x67, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x68, 0x6f, 0x73, 0x74, 0x52, + 0x65, 0x67, 0x65, 0x78, 0x12, 0x2b, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x2e, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x73, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x63, 0x70, 0x64, 0x75, 0x6d, 0x70, 0x5f, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x63, 0x70, + 0x64, 0x75, 0x6d, 0x70, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x22, 0x3a, 0x0a, 0x10, + 0x41, 0x64, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x26, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0e, 0x2e, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, + 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x13, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x50, + 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, 0x0a, + 0x16, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x43, 0x0a, + 0x17, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6d, 0x6f, 0x6e, 0x67, + 0x6f, 0x6c, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x73, 0x22, 0x12, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x3b, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6d, 0x6f, + 0x6e, 0x67, 0x6f, 0x6c, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x32, 0xe0, 0x01, 0x0a, 0x06, 0x4d, 0x6f, 0x6e, 0x47, 0x6f, 0x6c, 0x12, 0x40, + 0x0a, 0x09, 0x41, 0x64, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x18, 0x2e, 0x6d, 0x6f, + 0x6e, 0x67, 0x6f, 0x6c, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x2e, 0x41, + 0x64, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x40, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x2e, + 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, + 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x52, 0x0a, 0x0f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x46, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1e, 0x2e, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x2e, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6d, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x2e, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x24, 0x5a, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x6f, 0x2d, 0x6d, 0x6f, 0x6e, 0x64, 0x72, 0x65, + 0x67, 0x61, 0x6e, 0x74, 0x6f, 0x2f, 0x4d, 0x6f, 0x6e, 0x47, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_mongol_proto_rawDescOnce sync.Once + file_mongol_proto_rawDescData = file_mongol_proto_rawDesc +) + +func file_mongol_proto_rawDescGZIP() []byte { + file_mongol_proto_rawDescOnce.Do(func() { + file_mongol_proto_rawDescData = protoimpl.X.CompressGZIP(file_mongol_proto_rawDescData) + }) + return file_mongol_proto_rawDescData +} + +var file_mongol_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_mongol_proto_goTypes = []interface{}{ + (*EndpointData)(nil), // 0: mongol.EndpointData + (*CaptureConfig)(nil), // 1: mongol.CaptureConfig + (*Service)(nil), // 2: mongol.Service + (*Packet)(nil), // 3: mongol.Packet + (*Filter)(nil), // 4: mongol.Filter + (*Config)(nil), // 5: mongol.Config + (*AddPacketRequest)(nil), // 6: mongol.AddPacketRequest + (*AddPacketResponse)(nil), // 7: mongol.AddPacketResponse + (*RegisterFiltersRequest)(nil), // 8: mongol.RegisterFiltersRequest + (*RegisterFiltersResponse)(nil), // 9: mongol.RegisterFiltersResponse + (*GetConfigRequest)(nil), // 10: mongol.GetConfigRequest + (*GetConfigResponse)(nil), // 11: mongol.GetConfigResponse + (*timestamppb.Timestamp)(nil), // 12: google.protobuf.Timestamp +} +var file_mongol_proto_depIdxs = []int32{ + 1, // 0: mongol.Service.capture:type_name -> mongol.CaptureConfig + 0, // 1: mongol.Packet.endpoints:type_name -> mongol.EndpointData + 12, // 2: mongol.Packet.capture_time:type_name -> google.protobuf.Timestamp + 2, // 3: mongol.Config.services:type_name -> mongol.Service + 3, // 4: mongol.AddPacketRequest.packet:type_name -> mongol.Packet + 4, // 5: mongol.RegisterFiltersResponse.filters:type_name -> mongol.Filter + 5, // 6: mongol.GetConfigResponse.config:type_name -> mongol.Config + 6, // 7: mongol.MonGol.AddPacket:input_type -> mongol.AddPacketRequest + 10, // 8: mongol.MonGol.GetConfig:input_type -> mongol.GetConfigRequest + 8, // 9: mongol.MonGol.RegisterFilters:input_type -> mongol.RegisterFiltersRequest + 7, // 10: mongol.MonGol.AddPacket:output_type -> mongol.AddPacketResponse + 11, // 11: mongol.MonGol.GetConfig:output_type -> mongol.GetConfigResponse + 9, // 12: mongol.MonGol.RegisterFilters:output_type -> mongol.RegisterFiltersResponse + 10, // [10:13] is the sub-list for method output_type + 7, // [7:10] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name +} + +func init() { file_mongol_proto_init() } +func file_mongol_proto_init() { + if File_mongol_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_mongol_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EndpointData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mongol_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CaptureConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mongol_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Service); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mongol_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Packet); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mongol_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Filter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mongol_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Config); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mongol_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPacketRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mongol_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AddPacketResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mongol_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegisterFiltersRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mongol_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RegisterFiltersResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mongol_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetConfigRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_mongol_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetConfigResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_mongol_proto_rawDesc, + NumEnums: 0, + NumMessages: 12, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_mongol_proto_goTypes, + DependencyIndexes: file_mongol_proto_depIdxs, + MessageInfos: file_mongol_proto_msgTypes, + }.Build() + File_mongol_proto = out.File + file_mongol_proto_rawDesc = nil + file_mongol_proto_goTypes = nil + file_mongol_proto_depIdxs = nil +} diff --git a/lib/mongol/mongol_grpc.pb.go b/lib/mongol/mongol_grpc.pb.go new file mode 100644 index 0000000..de6f030 --- /dev/null +++ b/lib/mongol/mongol_grpc.pb.go @@ -0,0 +1,170 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package MonGol + +import ( + "context" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion7 + +// MonGolClient is the client API for MonGol service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type MonGolClient interface { + AddPacket(ctx context.Context, in *AddPacketRequest, opts ...grpc.CallOption) (*AddPacketResponse, error) + GetConfig(ctx context.Context, in *GetConfigRequest, opts ...grpc.CallOption) (*GetConfigResponse, error) + RegisterFilters(ctx context.Context, in *RegisterFiltersRequest, opts ...grpc.CallOption) (*RegisterFiltersResponse, error) +} + +type monGolClient struct { + cc grpc.ClientConnInterface +} + +func NewMonGolClient(cc grpc.ClientConnInterface) MonGolClient { + return &monGolClient{cc} +} + +func (c *monGolClient) AddPacket(ctx context.Context, in *AddPacketRequest, opts ...grpc.CallOption) (*AddPacketResponse, error) { + out := new(AddPacketResponse) + err := c.cc.Invoke(ctx, "/mongol.MonGol/AddPacket", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *monGolClient) GetConfig(ctx context.Context, in *GetConfigRequest, opts ...grpc.CallOption) (*GetConfigResponse, error) { + out := new(GetConfigResponse) + err := c.cc.Invoke(ctx, "/mongol.MonGol/GetConfig", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *monGolClient) RegisterFilters(ctx context.Context, in *RegisterFiltersRequest, opts ...grpc.CallOption) (*RegisterFiltersResponse, error) { + out := new(RegisterFiltersResponse) + err := c.cc.Invoke(ctx, "/mongol.MonGol/RegisterFilters", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MonGolServer is the server API for MonGol service. +// All implementations must embed UnimplementedMonGolServer +// for forward compatibility +type MonGolServer interface { + AddPacket(context.Context, *AddPacketRequest) (*AddPacketResponse, error) + GetConfig(context.Context, *GetConfigRequest) (*GetConfigResponse, error) + RegisterFilters(context.Context, *RegisterFiltersRequest) (*RegisterFiltersResponse, error) + mustEmbedUnimplementedMonGolServer() +} + +// UnimplementedMonGolServer must be embedded to have forward compatible implementations. +type UnimplementedMonGolServer struct { +} + +func (UnimplementedMonGolServer) AddPacket(context.Context, *AddPacketRequest) (*AddPacketResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddPacket not implemented") +} +func (UnimplementedMonGolServer) GetConfig(context.Context, *GetConfigRequest) (*GetConfigResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetConfig not implemented") +} +func (UnimplementedMonGolServer) RegisterFilters(context.Context, *RegisterFiltersRequest) (*RegisterFiltersResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RegisterFilters not implemented") +} +func (UnimplementedMonGolServer) mustEmbedUnimplementedMonGolServer() {} + +// UnsafeMonGolServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to MonGolServer will +// result in compilation errors. +type UnsafeMonGolServer interface { + mustEmbedUnimplementedMonGolServer() +} + +func RegisterMonGolServer(s grpc.ServiceRegistrar, srv MonGolServer) { + s.RegisterService(&_MonGol_serviceDesc, srv) +} + +func _MonGol_AddPacket_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AddPacketRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MonGolServer).AddPacket(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/mongol.MonGol/AddPacket", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MonGolServer).AddPacket(ctx, req.(*AddPacketRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _MonGol_GetConfig_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetConfigRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MonGolServer).GetConfig(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/mongol.MonGol/GetConfig", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MonGolServer).GetConfig(ctx, req.(*GetConfigRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _MonGol_RegisterFilters_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RegisterFiltersRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MonGolServer).RegisterFilters(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/mongol.MonGol/RegisterFilters", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MonGolServer).RegisterFilters(ctx, req.(*RegisterFiltersRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _MonGol_serviceDesc = grpc.ServiceDesc{ + ServiceName: "mongol.MonGol", + HandlerType: (*MonGolServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "AddPacket", + Handler: _MonGol_AddPacket_Handler, + }, + { + MethodName: "GetConfig", + Handler: _MonGol_GetConfig_Handler, + }, + { + MethodName: "RegisterFilters", + Handler: _MonGol_RegisterFilters_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "mongol.proto", +}