@@ -3,7 +3,9 @@ package http
3
3
import (
4
4
"compress/gzip"
5
5
"context"
6
+ "flag"
6
7
"fmt"
8
+ "net"
7
9
"net/http"
8
10
"strings"
9
11
"time"
@@ -14,6 +16,7 @@ import (
14
16
"github.com/kentik/ktranslate/pkg/eggs/kmux"
15
17
"github.com/kentik/ktranslate/pkg/eggs/logger"
16
18
"github.com/kentik/ktranslate/pkg/kt"
19
+ "github.com/kentik/ktranslate/pkg/util/ic"
17
20
)
18
21
19
22
type KentikHttpListener struct {
@@ -35,6 +38,14 @@ const (
35
38
Listen = "/input"
36
39
)
37
40
41
+ var (
42
+ useAsRemoteIP string
43
+ )
44
+
45
+ func init () {
46
+ flag .StringVar (& useAsRemoteIP , "http.remote_ip" , "" , "If set, ignore actual remote IP and use this for device mapping." )
47
+ }
48
+
38
49
func NewHttpListener (ctx context.Context , host string , log logger.Underlying , registry go_metrics.Registry , jchfChan chan []* kt.JCHF , apic * api.KentikApi ) (* KentikHttpListener , error ) {
39
50
ks := KentikHttpListener {
40
51
ContextL : logger .NewContextLFromUnderlying (logger.SContext {S : "Http" }, log ),
@@ -55,6 +66,105 @@ func (ks *KentikHttpListener) RegisterRoutes(r *kmux.Router) {
55
66
r .HandleFunc (Listen + "/telegraf/standard" , ks .wrap (ks .readStandard ))
56
67
r .HandleFunc (Listen + "/telegraf/batch" , ks .wrap (ks .readBatch ))
57
68
r .HandleFunc (Listen + "/ktranslate/jchf" , ks .wrap (ks .readJCHF ))
69
+ r .HandleFunc (Listen + "/gigamon/batch" , ks .wrap (ks .readGigaBatch ))
70
+ }
71
+
72
+ type gigaEvent struct {
73
+ Timestamp string `json:"ts"`
74
+ Vendor string `json:"vendor"`
75
+ Version string `json:"version"`
76
+ Generator string `json:"generator"`
77
+ SrcIP net.IP `json:"src_ip"`
78
+ DstIP net.IP `json:"dst_ip"`
79
+ Protocol int `json:"protocol,string"`
80
+ SrcPort int `json:"src_port,string"`
81
+ DstPort int `json:"dst_port,string"`
82
+ SslCommonName string `json:"ssl_common_name"`
83
+ SslIssuer string `json:"ssl_issuer"`
84
+ SslValidityNotBefore string `json:"ssl_validity_not_before"`
85
+ SslValidityNotAdter string `json:"ssl_validity_not_after"`
86
+ SslExtSigAlgorithumScheme int `json:"ssl_ext_sig_algorithm_scheme,string"`
87
+ SslExtSigAlgorithumHash int `json:"ssl_ext_sig_algorithm_hash,string"`
88
+ SslExtSigAlgorithumSig int `json:"ssl_ext_sig_algorithm_sig,string"`
89
+ AppId int `json:"app_id,string"`
90
+ SrcPackets int `json:"src_packets,string"`
91
+ DstPackets int `json:"dst_packets,string"`
92
+ AppName string `json:"app_name"`
93
+ SrcBytes int `json:"src_bytes,string"`
94
+ DstBytes int `json:"dst_bytes,string"`
95
+ Id string `json:"id"`
96
+ SeqNum int `json:"seq_num,string"`
97
+ }
98
+
99
+ func (ks * KentikHttpListener ) readGigaBatch (w http.ResponseWriter , r * http.Request ) {
100
+ var wrap []gigaEvent
101
+
102
+ // Decode body in gzip format if the request header is set this way.
103
+ body := r .Body
104
+ if r .Header .Get ("Content-Encoding" ) == "gzip" {
105
+ z , err := gzip .NewReader (r .Body )
106
+ if err != nil {
107
+ panic (http .StatusInternalServerError )
108
+ }
109
+ body = z
110
+ }
111
+ defer body .Close ()
112
+
113
+ if err := json .NewDecoder (body ).Decode (& wrap ); err != nil {
114
+ ks .Infof ("Cannot decode input: %v" , err )
115
+ panic (http .StatusInternalServerError )
116
+ }
117
+ w .WriteHeader (http .StatusOK )
118
+
119
+ remoteIP := getIP (r )
120
+ out := make ([]* kt.JCHF , len (wrap ))
121
+ for i , m := range wrap {
122
+ out [i ] = ks .getGigaJCHF (& m , remoteIP )
123
+ }
124
+
125
+ ks .metrics .Messages .Mark (int64 (len (out )))
126
+ ks .jchfChan <- out
127
+ }
128
+
129
+ func (ks * KentikHttpListener ) getGigaJCHF (event * gigaEvent , remoteIP string ) * kt.JCHF {
130
+ in := kt .NewJCHF ()
131
+ in .Timestamp = time .Now ().Unix ()
132
+ in .CustomStr = map [string ]string {
133
+ "timestamp" : event .Timestamp ,
134
+ "vendor" : event .Vendor ,
135
+ "version" : event .Version ,
136
+ "generator" : event .Generator ,
137
+ "app_name" : event .AppName ,
138
+ "id" : event .Id ,
139
+ "ssl_common_name" : event .SslCommonName ,
140
+ }
141
+ in .CustomInt = map [string ]int32 {
142
+ "app_id" : int32 (event .AppId ),
143
+ }
144
+ in .CustomBigInt = map [string ]int64 {
145
+ "seq_num" : int64 (event .SeqNum ),
146
+ }
147
+ in .EventType = event .Vendor
148
+ in .Provider = kt .ProviderHttpDevice
149
+ in .SrcAddr = event .SrcIP .String ()
150
+ in .DstAddr = event .DstIP .String ()
151
+ in .Protocol = ic .PROTO_NAMES [uint16 (event .Protocol )]
152
+ in .L4SrcPort = uint32 (event .SrcPort )
153
+ in .L4DstPort = uint32 (event .DstPort )
154
+ in .InPkts = uint64 (event .SrcPackets )
155
+ in .OutPkts = uint64 (event .DstPackets )
156
+ in .InBytes = uint64 (event .SrcBytes )
157
+ in .OutBytes = uint64 (event .DstBytes )
158
+
159
+ if dev , ok := ks .devices [remoteIP ]; ok {
160
+ in .DeviceName = dev .Name // Copy in any of these info we get
161
+ in .DeviceId = dev .ID
162
+ in .CompanyId = dev .CompanyID
163
+ in .SampleRate = dev .SampleRate
164
+ dev .SetUserTags (in .CustomStr )
165
+ }
166
+
167
+ return in
58
168
}
59
169
60
170
type basic struct {
@@ -219,6 +329,9 @@ type handler func(http.ResponseWriter, *http.Request)
219
329
func getIP (r * http.Request ) string {
220
330
res := r .Header .Get ("X-FORWARDED-FOR" )
221
331
if res == "" {
332
+ if useAsRemoteIP != "" {
333
+ return useAsRemoteIP
334
+ }
222
335
res = r .RemoteAddr
223
336
}
224
337
pts := strings .SplitN (res , ":" , 2 )
0 commit comments