main.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. package main
  2. import (
  3. "bufio"
  4. "bytes"
  5. "crypto/sha1"
  6. "encoding/csv"
  7. "encoding/json"
  8. "flag"
  9. "fmt"
  10. "io"
  11. "log"
  12. "math/rand"
  13. "net"
  14. "net/http"
  15. "os"
  16. "strings"
  17. "time"
  18. "github.com/BurntSushi/toml"
  19. "github.com/google/gopacket"
  20. "github.com/google/gopacket/layers"
  21. "github.com/google/gopacket/pcap"
  22. "github.com/nats-io/nats"
  23. "github.com/nats-io/nats/encoders/protobuf"
  24. "git.scraperwall.com/scw/ajp13"
  25. "git.scraperwall.com/scw/data"
  26. "git.scraperwall.com/scw/ip"
  27. )
  28. var (
  29. doLiveCapture = flag.Bool("live", false, "Capture data in real time from a given interface")
  30. iface = flag.String("interface", "eth0", "Interface to get packets from")
  31. snapshotLen = flag.Int("snapshot-len", 8192, "Snapshot Length in Bytes")
  32. filter = flag.String("filter", "tcp", "PCAP filter expression")
  33. promiscuous = flag.Bool("promiscuous", false, "Switch interface into promiscuous mode?")
  34. natsURL = flag.String("nats-url", "nats://127.0.0.1:4222", "The URL of the NATS server")
  35. natsUser = flag.String("nats-user", "", "The user for NATS authentication")
  36. natsPassword = flag.String("nats-password", "", "The password for NATS authentication")
  37. natsQueue = flag.String("nats-queue", "requests", "The NATS queue name")
  38. natsCA = flag.String("nats-ca", "", "CA chain for NATS TLS")
  39. sleepFor = flag.Duration("sleep", 0, "Sleep this long between sending data (only when replaying a file)")
  40. requestsFile = flag.String("requests", "", "CSV file containing requests (IP and URL)")
  41. protocol = flag.String("protocol", "http", "which protocol to parse: http or ajp13")
  42. useXForwardedAsSource = flag.Bool("use-x-forwarded", false, "Use the IP address in X-Forwarded-For as source")
  43. trace = flag.Bool("trace", false, "Trace the packet capturing")
  44. apacheLog = flag.String("apache-log", "", "Parse an Apache Log file")
  45. apacheReplay = flag.String("apache-replay", "", "Apache log file to replay into the system")
  46. nginxLog = flag.String("nginx-log", "", "Nginx log file to tail")
  47. nginxFormat = flag.String("nginx-format", "", "The nginx log file format")
  48. nginxReplay = flag.String("nginx-replay", "", "Replay this nginx logfile")
  49. hostName = flag.String("hostname", "", "Override the captured hostname with this one")
  50. accessWatchKey = flag.String("access-watch-key", "", "access.watch API key")
  51. configFile = flag.String("config", "", "The location of the TOML config file")
  52. rpcAddr = flag.String("rpc-address", "", "The address where the RPC server is listening")
  53. beQuiet = flag.Bool("quiet", true, "Be quiet")
  54. doVersion = flag.Bool("version", false, "Show version information")
  55. natsEC *nats.EncodedConn
  56. natsJSONEC *nats.EncodedConn
  57. rpcClient *ScwRPC
  58. natsErrorChan chan error
  59. natsIsAvailable bool
  60. count uint64
  61. timeout = -1 * time.Second
  62. ipPriv *ip.IP
  63. config Config
  64. // Version contains the program Version, e.g. 1.0.1
  65. Version string
  66. // BuildDate contains the date and time at which the program was compiled
  67. BuildDate string
  68. )
  69. // Config contains the program configuration
  70. type Config struct {
  71. Live bool
  72. Interface string
  73. SnapshotLen int
  74. Filter string
  75. Promiscuous bool
  76. NatsURL string
  77. NatsQueue string
  78. NatsUser string
  79. NatsPassword string
  80. NatsCA string
  81. SleepFor duration
  82. RequestsFile string
  83. UseXForwardedAsSource bool
  84. Quiet bool
  85. Protocol string
  86. Trace bool
  87. ApacheLog string
  88. ApacheReplay string
  89. NginxLog string
  90. NginxLogFormat string
  91. NginxReplay string
  92. HostName string
  93. AccessWatchKey string
  94. RPCAddress string
  95. }
  96. type duration struct {
  97. time.Duration
  98. }
  99. func (d *duration) UnmarshalText(text []byte) error {
  100. var err error
  101. d.Duration, err = time.ParseDuration(string(text))
  102. return err
  103. }
  104. func (c Config) print() {
  105. fmt.Printf("Live: %t\n", c.Live)
  106. fmt.Printf("Interface: %s\n", c.Interface)
  107. fmt.Printf("SnapshotLen: %d\n", c.SnapshotLen)
  108. fmt.Printf("Filter: %s\n", c.Filter)
  109. fmt.Printf("Promiscuous: %t\n", c.Promiscuous)
  110. fmt.Printf("NatsURL: %s\n", c.NatsURL)
  111. fmt.Printf("NatsQueue: %s\n", c.NatsQueue)
  112. fmt.Printf("NatsUser: %s\n", c.NatsUser)
  113. fmt.Printf("NatsPassword: %s\n", c.NatsPassword)
  114. fmt.Printf("NatsCA: %s\n", c.NatsCA)
  115. fmt.Printf("SleepFor: %s\n", c.SleepFor.String())
  116. fmt.Printf("RequestsFile: %s\n", c.RequestsFile)
  117. fmt.Printf("Apache Log: %s\n", c.ApacheLog)
  118. fmt.Printf("Apache Replay: %s\n", c.ApacheReplay)
  119. fmt.Printf("Nginx Log: %s\n", c.NginxLog)
  120. fmt.Printf("Nginx Log Format: %s\n", c.NginxLogFormat)
  121. fmt.Printf("NginxReplay: %s\n", c.NginxReplay)
  122. fmt.Printf("HostName: %s\n", c.HostName)
  123. fmt.Printf("AccessWatchKey: %s\n", c.AccessWatchKey)
  124. fmt.Printf("UseXForwardedAsSource: %t\n", c.UseXForwardedAsSource)
  125. fmt.Printf("Protocol: %s\n", c.Protocol)
  126. fmt.Printf("RPCAddress: %s\n", c.RPCAddress)
  127. fmt.Printf("Quiet: %t\n", c.Quiet)
  128. fmt.Printf("Trace: %t\n", c.Trace)
  129. }
  130. func init() {
  131. flag.Parse()
  132. nats.RegisterEncoder(protobuf.PROTOBUF_ENCODER, &protobuf.ProtobufEncoder{})
  133. }
  134. func main() {
  135. if *doVersion {
  136. version()
  137. os.Exit(0)
  138. }
  139. loadConfig()
  140. // Output how many requests per second were sent
  141. if !config.Quiet {
  142. go func(c *uint64) {
  143. for {
  144. fmt.Printf("%d requests per second\n", *c)
  145. *c = 0
  146. time.Sleep(time.Second)
  147. }
  148. }(&count)
  149. }
  150. // NATS
  151. //
  152. if config.NatsURL == "" && config.AccessWatchKey == "" {
  153. log.Fatal("No NATS URL specified (-nats-url)!")
  154. }
  155. natsIsAvailable = false
  156. natsErrorChan = make(chan error, 1)
  157. err := connectToNATS()
  158. if err != nil && config.AccessWatchKey == "" {
  159. log.Fatal(err)
  160. }
  161. go natsWatchdog(natsErrorChan)
  162. // RPC
  163. //
  164. if config.RPCAddress != "" {
  165. rpcClient, err = NewScwRPC(config.RPCAddress)
  166. if err != nil {
  167. log.Fatal(err)
  168. }
  169. }
  170. // What should I do?
  171. if config.RequestsFile != "" {
  172. replayFile()
  173. } else if config.ApacheReplay != "" {
  174. apacheLogReplay(config.ApacheReplay)
  175. } else if config.NginxReplay != "" {
  176. nginxLogReplay(config.NginxReplay, config.NginxLogFormat)
  177. } else if config.ApacheLog != "" {
  178. apacheLogCapture(config.ApacheLog)
  179. } else if config.Live {
  180. fmt.Printf("live capture (%s, %s) to %s\n", config.Interface, config.Filter, config.NatsURL)
  181. liveCapture()
  182. } else if config.NginxLog != "" && config.NginxLogFormat != "" {
  183. nginxLogCapture(config.NginxLog, config.NginxLogFormat)
  184. }
  185. }
  186. func natsWatchdog(closedChan chan error) {
  187. var lastError error
  188. for err := range closedChan {
  189. if lastError != err {
  190. lastError = err
  191. log.Println(err)
  192. }
  193. if err != nats.ErrConnectionClosed {
  194. continue
  195. }
  196. RECONNECT:
  197. for {
  198. log.Printf("Reconnecting to NATS at %s\n", *natsURL)
  199. err := connectToNATS()
  200. if err == nil {
  201. break RECONNECT
  202. }
  203. time.Sleep(1 * time.Second)
  204. }
  205. }
  206. }
  207. func connectToNATS() error {
  208. var natsConn *nats.Conn
  209. var err error
  210. if config.NatsUser != "" && config.NatsPassword != "" && config.NatsCA != "" {
  211. natsConn, err = nats.Connect(config.NatsURL, nats.UserInfo(config.NatsUser, config.NatsPassword), nats.RootCAs(config.NatsCA))
  212. } else {
  213. if config.NatsPassword != "" && config.NatsUser != "" {
  214. natsConn, err = nats.Connect(config.NatsURL, nats.UserInfo(config.NatsUser, config.NatsPassword))
  215. } else {
  216. natsConn, err = nats.Connect(config.NatsURL)
  217. }
  218. }
  219. if err != nil {
  220. return err
  221. }
  222. natsEC, err = nats.NewEncodedConn(natsConn, protobuf.PROTOBUF_ENCODER)
  223. if err != nil {
  224. return fmt.Errorf("Encoded Connection: %v", err)
  225. }
  226. natsJSONEC, err = nats.NewEncodedConn(natsConn, nats.JSON_ENCODER)
  227. if err != nil {
  228. return fmt.Errorf("Encoded Connection: %v", err)
  229. }
  230. natsIsAvailable = true
  231. return nil
  232. }
  233. func liveCapture() {
  234. ipPriv = ip.NewIP()
  235. // PCAP setup
  236. //
  237. handle, err := pcap.OpenLive(config.Interface, int32(config.SnapshotLen), config.Promiscuous, timeout)
  238. if err != nil {
  239. log.Fatal(err)
  240. }
  241. defer handle.Close()
  242. err = handle.SetBPFFilter(config.Filter)
  243. if err != nil {
  244. log.Fatal(err)
  245. }
  246. packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
  247. for packet := range packetSource.Packets() {
  248. go processPacket(packet)
  249. }
  250. }
  251. func writeLogToWatch(r *data.Request) {
  252. h := map[string]string{}
  253. if r.AcceptEncoding != "" {
  254. h["Accept-Encoding"] = r.AcceptEncoding
  255. }
  256. if r.Accept != "" {
  257. h["Accept"] = r.Accept
  258. }
  259. if r.AcceptLanguage != "" {
  260. h["Accept-Language"] = r.AcceptLanguage
  261. }
  262. if r.Cookie != "" {
  263. h["Cookie"] = r.Cookie
  264. }
  265. if r.Host != "" {
  266. h["Host"] = r.Host
  267. }
  268. if r.Referer != "" {
  269. h["Referer"] = r.Referer
  270. }
  271. if r.UserAgent != "" {
  272. h["User-Agent"] = r.UserAgent
  273. }
  274. if r.Via != "" {
  275. h["Via"] = r.Via
  276. }
  277. if r.XForwardedFor != "" {
  278. h["X-Forwarded-For"] = r.XForwardedFor
  279. }
  280. if r.XRequestedWith != "" {
  281. h["X-Requested-With"] = r.XRequestedWith
  282. }
  283. data := map[string]interface{}{
  284. "request": map[string]interface{}{
  285. "time": time.Unix(0, r.CreatedAt),
  286. "address": r.Source,
  287. "protocol": r.Protocol,
  288. "scheme": "https",
  289. "method": r.Method,
  290. "url": r.Url,
  291. "headers": h,
  292. },
  293. "response": map[string]interface{}{"status": "200"},
  294. }
  295. jdata, err := json.Marshal(data)
  296. client := &http.Client{}
  297. fmt.Println(string(jdata))
  298. buf := bytes.NewBuffer(jdata)
  299. req, err := http.NewRequest("POST", "https://log.access.watch/1.1/log", buf)
  300. req.Header.Add("Api-Key", config.AccessWatchKey)
  301. req.Header.Add("Accept", "application/json")
  302. req.Header.Add("Content-Type", "application/json")
  303. resp, err := client.Do(req)
  304. if err != nil {
  305. log.Println(err)
  306. }
  307. resp.Body.Close()
  308. }
  309. func publishRequest(queue string, request *data.Request) {
  310. if config.AccessWatchKey != "" {
  311. writeLogToWatch(request)
  312. return
  313. }
  314. if rpcClient != nil {
  315. select {
  316. case rpcClient.RChan <- request:
  317. default:
  318. }
  319. return
  320. }
  321. if !natsIsAvailable {
  322. if rand.Intn(100) == 0 {
  323. log.Println("nats connection is not available")
  324. }
  325. return
  326. }
  327. if err := natsEC.Publish(config.NatsQueue, request); err != nil {
  328. natsErrorChan <- err
  329. if err == nats.ErrConnectionClosed {
  330. natsIsAvailable = false
  331. }
  332. }
  333. }
  334. // processPacket receives a raw packet from pcap, builds a Request item from it and sends it to the queue
  335. func processPacket(packet gopacket.Packet) {
  336. hasIPv4 := false
  337. var ipSrc, ipDst string
  338. // IPv4
  339. if ipLayer := packet.Layer(layers.LayerTypeIPv4); ipLayer != nil {
  340. ip := ipLayer.(*layers.IPv4)
  341. ipSrc = ip.SrcIP.String()
  342. ipDst = ip.DstIP.String()
  343. hasIPv4 = true
  344. }
  345. // IPv6
  346. if !hasIPv4 {
  347. if ipLayer := packet.Layer(layers.LayerTypeIPv6); ipLayer != nil {
  348. ip := ipLayer.(*layers.IPv6)
  349. ipSrc = ip.SrcIP.String()
  350. ipDst = ip.DstIP.String()
  351. }
  352. }
  353. // TCP
  354. tcpLayer := packet.Layer(layers.LayerTypeTCP)
  355. if tcpLayer == nil {
  356. return
  357. }
  358. tcp, _ := tcpLayer.(*layers.TCP)
  359. portSrc := tcp.SrcPort
  360. portDst := tcp.DstPort
  361. sequence := tcp.Seq
  362. applicationLayer := packet.ApplicationLayer()
  363. if applicationLayer == nil {
  364. return
  365. }
  366. count++
  367. if len(applicationLayer.Payload()) < 50 {
  368. log.Println("application layer too small!")
  369. return
  370. }
  371. request := data.Request{
  372. IpSrc: ipSrc,
  373. IpDst: ipDst,
  374. PortSrc: uint32(portSrc),
  375. PortDst: uint32(portDst),
  376. TcpSeq: uint32(sequence),
  377. CreatedAt: packet.Metadata().CaptureInfo.Timestamp.UnixNano(),
  378. }
  379. switch config.Protocol {
  380. case "http":
  381. err := processHTTP(&request, applicationLayer.Payload())
  382. if err != nil {
  383. log.Println(err)
  384. return
  385. }
  386. case "ajp13":
  387. err := processAJP13(&request, applicationLayer.Payload())
  388. if err != nil {
  389. log.Println(err)
  390. return
  391. }
  392. }
  393. if config.UseXForwardedAsSource && request.XForwardedFor != "" {
  394. if strings.Contains(request.XForwardedFor, ",") {
  395. ips := strings.Split(request.XForwardedFor, ",")
  396. for i := len(ips) - 1; i >= 0; i-- {
  397. ipRaw := strings.TrimSpace(ips[i])
  398. ipAddr := net.ParseIP(ipRaw)
  399. if ipAddr != nil && !ipPriv.IsPrivate(ipAddr) {
  400. request.Source = ipRaw
  401. break
  402. }
  403. }
  404. } else {
  405. ipAddr := net.ParseIP(strings.TrimSpace(request.XForwardedFor))
  406. if !ipPriv.IsPrivate(ipAddr) {
  407. request.Source = request.XForwardedFor
  408. }
  409. }
  410. }
  411. if request.Source == request.IpSrc && request.XRealIP != "" {
  412. request.Source = request.XRealIP
  413. }
  414. if config.Trace {
  415. log.Printf("[%s] %s\n", request.Source, request.Url)
  416. }
  417. publishRequest(config.NatsQueue, &request)
  418. }
  419. func processAJP13(request *data.Request, appData []byte) error {
  420. a, err := ajp13.Parse(appData)
  421. if err != nil {
  422. return fmt.Errorf("Failed to parse AJP13 request: %s", err)
  423. }
  424. request.Url = a.URI
  425. request.Method = a.Method()
  426. request.Host = a.Server
  427. request.Protocol = a.Version
  428. request.Origin = a.RemoteAddr.String()
  429. request.Source = a.RemoteAddr.String()
  430. if v, ok := a.Header("Referer"); ok {
  431. request.Referer = v
  432. }
  433. if v, ok := a.Header("Connection"); ok {
  434. request.Connection = v
  435. }
  436. if v, ok := a.Header("X-Forwarded-For"); ok {
  437. request.XForwardedFor = v
  438. }
  439. if v, ok := a.Header("X-Real-IP"); ok {
  440. request.XRealIP = v
  441. }
  442. if v, ok := a.Header("X-Requested-With"); ok {
  443. request.XRequestedWith = v
  444. }
  445. if v, ok := a.Header("Accept-Encoding"); ok {
  446. request.AcceptEncoding = v
  447. }
  448. if v, ok := a.Header("Accept-Language"); ok {
  449. request.AcceptLanguage = v
  450. }
  451. if v, ok := a.Header("User-Agent"); ok {
  452. request.UserAgent = v
  453. }
  454. if v, ok := a.Header("Accept"); ok {
  455. request.Accept = v
  456. }
  457. if v, ok := a.Header("Cookie"); ok {
  458. request.Cookie = v
  459. }
  460. if v, ok := a.Header("X-Forwarded-Host"); ok {
  461. if v != request.Host {
  462. request.Host = v
  463. }
  464. }
  465. return nil
  466. }
  467. func processHTTP(request *data.Request, appData []byte) error {
  468. reader := bufio.NewReader(strings.NewReader(string(appData)))
  469. req, err := http.ReadRequest(reader)
  470. if err != nil {
  471. return fmt.Errorf("Failed to parse HTTP header: %s", err)
  472. }
  473. request.Url = req.URL.String()
  474. request.Method = req.Method
  475. request.Referer = req.Referer()
  476. request.Host = req.Host
  477. request.Protocol = req.Proto
  478. request.Origin = request.Host
  479. if _, ok := req.Header["Connection"]; ok {
  480. request.Connection = req.Header["Connection"][0]
  481. }
  482. if _, ok := req.Header["X-Forwarded-For"]; ok {
  483. request.XForwardedFor = req.Header["X-Forwarded-For"][0]
  484. }
  485. // CloudFlare: override X-Forwarded for since it is tainted by cloudflare
  486. if _, ok := req.Header["True-Client-Ip"]; ok {
  487. request.XForwardedFor = req.Header["True-Client-Ip"][0]
  488. }
  489. if _, ok := req.Header["X-Real-Ip"]; ok {
  490. request.XRealIP = req.Header["X-Real-Ip"][0]
  491. }
  492. if _, ok := req.Header["X-Requested-With"]; ok {
  493. request.XRequestedWith = req.Header["X-Requested-With"][0]
  494. }
  495. if _, ok := req.Header["Accept-Encoding"]; ok {
  496. request.AcceptEncoding = req.Header["Accept-Encoding"][0]
  497. }
  498. if _, ok := req.Header["Accept-Language"]; ok {
  499. request.AcceptLanguage = req.Header["Accept-Language"][0]
  500. }
  501. if _, ok := req.Header["User-Agent"]; ok {
  502. request.UserAgent = req.Header["User-Agent"][0]
  503. }
  504. if _, ok := req.Header["Accept"]; ok {
  505. request.Accept = req.Header["Accept"][0]
  506. }
  507. if _, ok := req.Header["Cookie"]; ok {
  508. request.Cookie = req.Header["Cookie"][0]
  509. }
  510. request.Source = request.IpSrc
  511. return nil
  512. }
  513. // replayFile takes a file containing a list of requests (SourceIP Url) and queues the requests
  514. // e.g.
  515. // 157.55.39.229 /gross-gerau/12012260-beate-anstatt
  516. // 103.232.100.98 /weinsheim-eifel/13729444-plus-warenhandelsges-mbh
  517. func replayFile() {
  518. var req data.Request
  519. var startTs time.Time
  520. var endTs time.Time
  521. rand.Seed(time.Now().UnixNano())
  522. for {
  523. fh, err := os.Open(config.RequestsFile)
  524. if err != nil {
  525. log.Fatalf("Failed to open request file '%s': %s", config.RequestsFile, err)
  526. }
  527. c := csv.NewReader(fh)
  528. c.Comma = ' '
  529. for {
  530. if config.SleepFor.Duration > time.Nanosecond {
  531. startTs = time.Now()
  532. }
  533. r, err := c.Read()
  534. if err == io.EOF {
  535. break
  536. }
  537. if err != nil {
  538. log.Println(err)
  539. continue
  540. }
  541. req.IpSrc = r[0]
  542. req.Source = r[0]
  543. req.Url = r[1]
  544. req.UserAgent = "Munch/1.0"
  545. req.Host = "demo.scraperwall.com"
  546. req.CreatedAt = time.Now().UnixNano()
  547. publishRequest(config.NatsQueue, &req)
  548. if strings.Index(r[1], ".") < 0 {
  549. hash := sha1.New()
  550. io.WriteString(hash, r[0])
  551. fp := data.Fingerprint{
  552. ClientID: "scw",
  553. Fingerprint: fmt.Sprintf("%x", hash.Sum(nil)),
  554. Remote: r[0],
  555. Url: r[1],
  556. Source: r[0],
  557. CreatedAt: time.Now(),
  558. }
  559. if strings.HasPrefix(r[0], "50.31.") {
  560. fp.Fingerprint = "a1f2c2ee560ce6580d66d451a9c8dfbf"
  561. natsJSONEC.Publish("fingerprints_scw", fp)
  562. } else if rand.Intn(10) < 5 {
  563. natsJSONEC.Publish("fingerprints_scw", fp)
  564. }
  565. }
  566. count++
  567. if config.SleepFor.Duration >= time.Nanosecond {
  568. endTs = time.Now()
  569. if endTs.Before(startTs.Add(config.SleepFor.Duration)) {
  570. time.Sleep(config.SleepFor.Duration - endTs.Sub(startTs))
  571. }
  572. }
  573. }
  574. }
  575. }
  576. func loadConfig() {
  577. // initialize with values from the command line / environment
  578. config.Live = *doLiveCapture
  579. config.Interface = *iface
  580. config.SnapshotLen = *snapshotLen
  581. config.Filter = *filter
  582. config.Promiscuous = *promiscuous
  583. config.NatsURL = *natsURL
  584. config.NatsQueue = *natsQueue
  585. config.NatsUser = *natsUser
  586. config.NatsPassword = *natsPassword
  587. config.NatsCA = *natsCA
  588. config.SleepFor.Duration = *sleepFor
  589. config.RequestsFile = *requestsFile
  590. config.UseXForwardedAsSource = *useXForwardedAsSource
  591. config.Protocol = *protocol
  592. config.ApacheLog = *apacheLog
  593. config.ApacheReplay = *apacheReplay
  594. config.NginxLog = *nginxLog
  595. config.NginxLogFormat = *nginxFormat
  596. config.NginxReplay = *nginxReplay
  597. config.HostName = *hostName
  598. config.Quiet = *beQuiet
  599. config.Trace = *trace
  600. config.AccessWatchKey = *accessWatchKey
  601. config.RPCAddress = *rpcAddr
  602. if *configFile == "" {
  603. return
  604. }
  605. _, err := os.Stat(*configFile)
  606. if err != nil {
  607. log.Printf("%s: %s\n", *configFile, err)
  608. return
  609. }
  610. if _, err = toml.DecodeFile(*configFile, &config); err != nil {
  611. log.Printf("%s: %s\n", *configFile, err)
  612. }
  613. if !config.Quiet {
  614. config.print()
  615. }
  616. }
  617. // version outputs build information...
  618. func version() {
  619. fmt.Printf("munchclient %s, built on %s\n", Version, BuildDate)
  620. }