├── .gitattributes ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── assets └── packiffer.png ├── build.py ├── go.mod ├── go.sum └── src ├── core ├── afpacket.go ├── afxdp.go ├── api.go ├── freebsdapiwrapper.go ├── iptables.go ├── linuxapiwrapper.go ├── macapiwrapper.go ├── packetdump.go ├── packetfilter_linux.go ├── packetfilter_windows.go ├── packetinject.go ├── packetparser.go ├── packetsniff.go ├── packiffer.go └── windowsapiwrapper.go ├── ebpf ├── xdp_block_address.c └── xdp_block_address.rs ├── files ├── InjectConstructed.json ├── InjectRaw.txt └── firewall.txt └── web ├── controllers ├── auth │ └── auth.go └── base.go ├── go.mod ├── init └── init.go ├── models ├── auth │ └── login_model.go └── base.go └── routes ├── auth └── auth.go └── base.go /.gitattributes: -------------------------------------------------------------------------------- 1 | src/ui/* linguist-vendored -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/* 2 | *.pcap 3 | bpf_helpers.h 4 | *.elf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020-2021, Massoud Asadi 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GOCMD := go 2 | GOBUILD := $(GOCMD) build 3 | GOCLEAN := $(GOCMD) clean 4 | CLANG := clang 5 | CLANG_INCLUDE := -I../../.. 6 | 7 | GO_SOURCE := "./src/core/" 8 | GO_BINARY := packiffer 9 | 10 | EBPF_SOURCE := src/ebpf/xdp_block_address.c 11 | EBPF_BINARY := xdp_block_address.elf 12 | 13 | all: build_bpf build_go 14 | 15 | build_bpf: $(EBPF_BINARY) 16 | 17 | build_go: $(GO_BINARY) 18 | 19 | clean: 20 | $(GOCLEAN) 21 | rm -f $(GO_BINARY) 22 | rm -f $(EBPF_BINARY) 23 | 24 | $(EBPF_BINARY): $(EBPF_SOURCE) 25 | $(CLANG) $(CLANG_INCLUDE) -O2 -target bpf -c $^ -o $@ 26 | 27 | $(GO_BINARY): 28 | $(GOBUILD) -v -o $@ $(GO_SOURCE) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Go Report Card](https://goreportcard.com/badge/github.com/massoudasadi/packiffer)](https://goreportcard.com/report/github.com/massoudasadi/packiffer) 2 | 3 | 4 | 5 | # Packiffer 6 | Packiffer is a lightweight cross-platform networking toolkit that let you sniff/analyze/inject/filter packets. 7 | 8 |
  9 | Features:
 10 |     -display list of network interfaces
 11 |     -sniff packets live from interface
 12 |     -set promiscuous mode on interface
 13 |     -apply filters to packets
 14 |     -transform selected packets from pcap file to another
 15 |     -inspect packets in terminal
 16 |     -inject packets into network
 17 |     -filter packets with specified destination ip
 18 | 
19 | 20 |
 21 | Modes:
 22 |     Sniff: 
 23 |         sniff packets live from interface
 24 | 
 25 |     Transform: 
 26 |         transform packets from offline pcap
 27 | 
 28 |     Inspect: 
 29 |         inspect & analysis packets from offline pcap files
 30 | 
 31 |     Inject: 
 32 |         Inject Raw & Constructed Packets
 33 | 
 34 |     Filter:
 35 |         Drop or Accept Packets
 36 | 
37 | 38 | # Prerequisites For Binary 39 |

Libpcap v1.9.1

40 |

Clang/LLVM (Only on Linux for eBPF XDP packet filtering)

41 |

Iptables (Only on Linux for Iptables packet filtering)

42 | 43 | # Prerequisites For Source 44 |

Golang v1.16

45 |

GoPacket v1.1.19

46 |

Go eBPF v0.0.0-20210223

47 |

Libpcap v1.9.1

48 |

Fiber v2.8.0

49 |

Clang/LLVM (Only on Linux for eBPF XDP packet filtering)

50 |

Iptables (Only on Linux for Iptables packet filtering)

51 | 52 | # How to get Packiffer 53 | Checkout packiffer git repo using git clone 54 | ``` 55 | git clone https://github.com/massoudasadi/packiffer.git 56 | cd packiffer 57 | ``` 58 | 59 | # Run Packiffer 60 | 61 | Sniff mode: 62 | ``` 63 | make build_go 64 | 65 | ./packiffer sniff 66 | 67 | ("i", "Specify interface name. Default is eth0") 68 | ("p", "Specify promiscuous mode. Default is false") 69 | ("f", "Specify filter query. Default is all") 70 | ("od", "Specify output directory. Defaultis packiffer directory") 71 | ("of", "Specify output file name. Defaultis interface name") 72 | ("sl", "Specify Snapshot Lenght. Default is 2014") 73 | ("t", "limit sniffing timeout. Default is 30 seconds") 74 | ("c", "Limit count of packets to sniff. Default is 1000") 75 | ``` 76 | 77 | transform mode: 78 | ``` 79 | make build_go 80 | 81 | ./packiffer transform 82 | 83 | ("f", "Specify filter query. Default is all") 84 | ("in", "Specify input pcap file") 85 | ("od", "Specify output directory.Default is packiffer directory") 86 | ("of", "Specify output file name.Default is interface name") 87 | ("c", "Limit count of packets to sniff. Default is1000") 88 | ``` 89 | 90 | inspect mode: 91 | ``` 92 | make build_go 93 | 94 | ./packiffer inspect 95 | 96 | ("in", "Specify input pcap file") 97 | ("f", "Specify filter query. Default is all") 98 | ("c", "Limit count of packets to sniff. Default is 1000") 99 | ``` 100 | 101 | inject mode: 102 | ``` 103 | make build_go 104 | 105 | ./packiffer inject 106 | 107 | ("i", "Specify interface name. Default is eth0") 108 | ("ir", "Specify Raw Packet Inject. Default is false") 109 | ("ic", "Specify Constructed Packet Inject. Default is False") 110 | ("f", "Specify Path to packet file. Default is inject.txt") 111 | ``` 112 | 113 | firewall mode: 114 | ``` 115 | make build_bpf 116 | make build_go 117 | 118 | ./packiffer firewall 119 | 120 | ("i", "Specify interface name. Default is eth0") 121 | ("f", "Specify Path to firewall file. Default is firewall.txt") 122 | ``` 123 | 124 | default mode: 125 | ``` 126 | ./packiffer 127 | 128 | ("h", "Specify help display. Default is false") 129 | ("d", "Specify devices display. Default is false") 130 | ``` 131 | 132 | # Examples 133 | Display list of network interfaces 134 | ``` 135 | ./packiffer -d 136 | ``` 137 | 138 | Sniff packets on 'eth0' and save packets in 'eth0.pcap' (promiscuous mode) until Ctrl+C pressed 139 | ``` 140 | ./packiffer sniff -i eth0 -p 141 | ``` 142 | 143 | transformonly udp packets from 'eth0.pcap' to 'eth0_udp.pcap' until Ctrl+C pressed 144 | ``` 145 | ./packiffer transform -in /path/to/eth0.pcap -of eth0_udp 146 | ``` 147 | 148 | inspect only tcp packets from pcap file 149 | ``` 150 | ./packiffer inspect -in /path/to/file.pcap -f tcp 151 | ``` 152 | 153 | inject constructed tcp packets from InjectConstructed.json 154 | ``` 155 | ./packiffer inject -i eth0 -ic -f /path/to/file.json 156 | ``` 157 | 158 | filter packets from ips inside firewall.txt 159 | ``` 160 | ./packiffer firewall -i eth0 -f /path/to/file.txt 161 | ``` 162 | -------------------------------------------------------------------------------- /assets/packiffer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/massoudasadi/packiffer/07a42fb93839e8a898e9ecbf36305d842473a6e9/assets/packiffer.png -------------------------------------------------------------------------------- /build.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | s = subprocess.getstatusoutput(f'make build_go') 3 | print(s) -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module packiffer 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/andybalholm/brotli v1.0.4 // indirect 7 | github.com/dropbox/goebpf v0.0.0-20220129191406-26833cbb7e4d 8 | github.com/fasthttp/websocket v1.5.0 // indirect 9 | github.com/gofiber/fiber/v2 v2.32.0 10 | github.com/gofiber/websocket/v2 v2.0.21 11 | github.com/google/gopacket v1.1.19 12 | github.com/klauspost/compress v1.15.1 // indirect 13 | github.com/savsgio/gotils v0.0.0-20220401102855-e56b59f40436 // indirect 14 | github.com/valyala/fasthttp v1.35.0 // indirect 15 | github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect 16 | golang.org/x/net v0.0.0-20220421235706-1d1ef9303861 // indirect 17 | golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect 18 | ) 19 | 20 | require ( 21 | github.com/valyala/bytebufferpool v1.0.0 // indirect 22 | github.com/valyala/tcplisten v1.0.0 // indirect 23 | github.com/vishvananda/netlink v1.2.0-beta // indirect 24 | ) 25 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= 2 | github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= 3 | github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= 4 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 5 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 6 | github.com/dropbox/goebpf v0.0.0-20220129191406-26833cbb7e4d h1:9NmkOLACrG2TMVw01myNGg5SVVjsETzkJW78gP1Ccz4= 7 | github.com/dropbox/goebpf v0.0.0-20220129191406-26833cbb7e4d/go.mod h1:U44fqiGgxszGKp6WDm/xtCXJqx4h2hDYnCpu4/m0uQk= 8 | github.com/fasthttp/websocket v1.4.6 h1:Zi0Z6sUUvLmtxXd/kMLVBVJPvck3bqPqMWUbwhUy0R8= 9 | github.com/fasthttp/websocket v1.4.6/go.mod h1:n0BlOQvJdPbTuBkZT0O5+jk/sp/1/VCzquR1BehI2F4= 10 | github.com/fasthttp/websocket v1.5.0 h1:B4zbe3xXyvIdnqjOZrafVFklCUq5ZLo/TqCt5JA1wLE= 11 | github.com/fasthttp/websocket v1.5.0/go.mod h1:n0BlOQvJdPbTuBkZT0O5+jk/sp/1/VCzquR1BehI2F4= 12 | github.com/gofiber/fiber/v2 v2.26.0 h1:Awnfqp3fqbZzV3wZWMRJ6Xo2U8X0Ls68M7tXjx52NcM= 13 | github.com/gofiber/fiber/v2 v2.26.0/go.mod h1:7efVWcBOZi1PyMWznnbitjnARPA7nYZxmQXJVod0bo0= 14 | github.com/gofiber/fiber/v2 v2.32.0 h1:lpgcGEq1UENv27uVuOaufAhU8wUKnX8yb9L7559Neec= 15 | github.com/gofiber/fiber/v2 v2.32.0/go.mod h1:CMy5ZLiXkn6qwthrl03YMyW1NLfj0rhxz2LKl4t7ZTY= 16 | github.com/gofiber/websocket/v2 v2.0.16 h1:OE/Vr2q9F5aipvKbnWGh9eVJoyuqYQV6ej1GQLB3OcM= 17 | github.com/gofiber/websocket/v2 v2.0.16/go.mod h1:h2dmeujDrnPfOJHmVE+iGyJx1AZKtOqiQ2Q2waTN3LY= 18 | github.com/gofiber/websocket/v2 v2.0.21 h1:mQEiLXBqFsNNlJc5dzFgSGeoqoEXYvIcdBQzAZBdbL0= 19 | github.com/gofiber/websocket/v2 v2.0.21/go.mod h1:AOdLDGRGMr9MXH0GjHD43xR17x5lzs0pd5E0/cEKYX8= 20 | github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 21 | github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= 22 | github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 23 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 24 | github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= 25 | github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 26 | github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw= 27 | github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 28 | github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 29 | github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A= 30 | github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 31 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 32 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 33 | github.com/savsgio/gotils v0.0.0-20211223103454-d0aaa54c5899/go.mod h1:oejLrk1Y/5zOF+c/aHtXqn3TFlzzbAgPWg8zBiAHDas= 34 | github.com/savsgio/gotils v0.0.0-20220201163454-d252f0a44d5b h1:ri8OZKT4xhe+5tOr7f7PWeTEx+iAsFy12vu97c892m4= 35 | github.com/savsgio/gotils v0.0.0-20220201163454-d252f0a44d5b/go.mod h1:oejLrk1Y/5zOF+c/aHtXqn3TFlzzbAgPWg8zBiAHDas= 36 | github.com/savsgio/gotils v0.0.0-20220401102855-e56b59f40436 h1:sfTahD3f2BSjx9U3R4K09PkNuZZWthT7g6vzTIXNWkM= 37 | github.com/savsgio/gotils v0.0.0-20220401102855-e56b59f40436/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4= 38 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 39 | github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= 40 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 41 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= 42 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 43 | github.com/valyala/fasthttp v1.32.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= 44 | github.com/valyala/fasthttp v1.33.0 h1:mHBKd98J5NcXuBddgjvim1i3kWzlng1SzLhrnBOU9g8= 45 | github.com/valyala/fasthttp v1.33.0/go.mod h1:KJRK/MXx0J+yd0c5hlR+s1tIHD72sniU8ZJjl97LIw4= 46 | github.com/valyala/fasthttp v1.35.0 h1:wwkR8mZn2NbigFsaw2Zj5r+xkmzjbrA/lyTmiSlal/Y= 47 | github.com/valyala/fasthttp v1.35.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= 48 | github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= 49 | github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= 50 | github.com/vishvananda/netlink v1.1.1-0.20200218174631-5f2fc868c2d0 h1:GNKyqfdQI0/lEYv+VHIzsECySOY+EDjT22Dl49OyGNA= 51 | github.com/vishvananda/netlink v1.1.1-0.20200218174631-5f2fc868c2d0/go.mod h1:FSQhuTO7eHT34mPzX+B04SUAjiqLxtXs1et0S6l9k4k= 52 | github.com/vishvananda/netlink v1.2.0-beta h1:CTNzkunO9iTkRaupF540+w47mexyQgNkA/ibnuKc39w= 53 | github.com/vishvananda/netlink v1.2.0-beta/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= 54 | github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= 55 | github.com/vishvananda/netns v0.0.0-20200520041808-52d707b772fe/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= 56 | github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= 57 | github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= 58 | github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= 59 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 60 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 61 | golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= 62 | golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 63 | golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 64 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 65 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 66 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 67 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 68 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 69 | golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 70 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 71 | golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 72 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= 73 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 74 | golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 75 | golang.org/x/net v0.0.0-20220421235706-1d1ef9303861 h1:yssD99+7tqHWO5Gwh81phT+67hg+KttniBr6UnEXOY8= 76 | golang.org/x/net v0.0.0-20220421235706-1d1ef9303861/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 77 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 78 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 79 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 80 | golang.org/x/sys v0.0.0-20200121082415-34d275377bf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 81 | golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 82 | golang.org/x/sys v0.0.0-20200722175500-76b94024e4b6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 83 | golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 84 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 85 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 86 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 87 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 88 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 89 | golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 90 | golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= 91 | golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 92 | golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 93 | golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc= 94 | golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 95 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 96 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 97 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 98 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 99 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 100 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 101 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 102 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 103 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 104 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 105 | gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 106 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 107 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 108 | -------------------------------------------------------------------------------- /src/core/afpacket.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package main 4 | -------------------------------------------------------------------------------- /src/core/afxdp.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package main 4 | 5 | import ( 6 | "bufio" 7 | "errors" 8 | "fmt" 9 | "log" 10 | "net" 11 | "os" 12 | "strings" 13 | "time" 14 | 15 | "github.com/dropbox/goebpf" 16 | ) 17 | 18 | type ipAddressList []string 19 | 20 | func (p *packiffer) runBPF() { 21 | 22 | var ipList ipAddressList 23 | 24 | f, perr := os.Open(p.File) 25 | 26 | if perr != nil { 27 | log.Fatal(perr) 28 | } 29 | 30 | defer f.Close() 31 | 32 | scanner := bufio.NewScanner(f) 33 | 34 | for scanner.Scan() { 35 | 36 | fmt.Println(scanner.Text()) 37 | ipList = append(ipList, scanner.Text()) 38 | } 39 | 40 | if err := scanner.Err(); err != nil { 41 | log.Fatal(err) 42 | } 43 | 44 | bpf := goebpf.NewDefaultEbpfSystem() 45 | 46 | err := bpf.LoadElf("xdp_block_address.elf") 47 | if err != nil { 48 | fatalError("LoadElf() failed: %v", err) 49 | } 50 | printBpfInfo(bpf) 51 | 52 | matches := bpf.GetMapByName("matches") 53 | if matches == nil { 54 | fatalError("eBPF map 'matches' not found") 55 | } 56 | blacklist := bpf.GetMapByName("blacklist") 57 | if blacklist == nil { 58 | fatalError("eBPF map 'blacklist' not found") 59 | } 60 | 61 | xdp := bpf.GetProgramByName("firewall") 62 | if xdp == nil { 63 | fatalError("Program 'firewall' not found.") 64 | } 65 | 66 | fmt.Println("Blacklisting IPv4 addresses...") 67 | for index, ip := range ipList { 68 | fmt.Printf("\t%s\n", ip) 69 | err := blacklist.Insert(goebpf.CreateLPMtrieKey(ip), index) 70 | if err != nil { 71 | fatalError("Unable to Insert into eBPF map: %v", err) 72 | } 73 | } 74 | fmt.Println() 75 | 76 | err = xdp.Load() 77 | if err != nil { 78 | fatalError("xdp.Load(): %v", err) 79 | } 80 | 81 | err = xdp.Attach(p.interfaceName) 82 | if err != nil { 83 | fatalError("xdp.Attach(): %v", err) 84 | } 85 | defer xdp.Detach() 86 | 87 | // // Add CTRL+C handler 88 | // ctrlC := make(chan os.Signal, 1) 89 | // signal.Notify(ctrlC, os.Interrupt) 90 | 91 | fmt.Println("XDP program successfully loaded and attached. Counters refreshed every second.") 92 | fmt.Println("Press CTRL+C to stop.") 93 | fmt.Println() 94 | 95 | ticker := time.NewTicker(1 * time.Second) 96 | for { 97 | select { 98 | case <-ticker.C: 99 | fmt.Println("IP DROPs") 100 | for i := 0; i < len(ipList); i++ { 101 | value, err := matches.LookupInt(i) 102 | if err != nil { 103 | fatalError("LookupInt failed: %v", err) 104 | } 105 | fmt.Printf("%18s %d\n", ipList[i], value) 106 | } 107 | fmt.Println() 108 | } 109 | } 110 | } 111 | 112 | func fatalError(format string, args ...interface{}) { 113 | fmt.Fprintf(os.Stderr, format+"\n", args...) 114 | os.Exit(1) 115 | } 116 | 117 | func printBpfInfo(bpf goebpf.System) { 118 | fmt.Println("Maps:") 119 | for _, item := range bpf.GetMaps() { 120 | fmt.Printf("\t%s: %v, Fd %v\n", item.GetName(), item.GetType(), item.GetFd()) 121 | } 122 | fmt.Println("\nPrograms:") 123 | for _, prog := range bpf.GetPrograms() { 124 | fmt.Printf("\t%s: %v, size %d, license \"%s\"\n", 125 | prog.GetName(), prog.GetType(), prog.GetSize(), prog.GetLicense(), 126 | ) 127 | 128 | } 129 | fmt.Println() 130 | } 131 | 132 | // Implements flag.Value 133 | func (i *ipAddressList) String() string { 134 | return fmt.Sprintf("%+v", *i) 135 | } 136 | 137 | // Implements flag.Value 138 | func (i *ipAddressList) Set(value string) error { 139 | if len(*i) == 16 { 140 | return errors.New("up to 16 IPv4 addresses supported") 141 | } 142 | // Validate that value is correct IPv4 address 143 | if !strings.Contains(value, "/") { 144 | value += "/32" 145 | } 146 | if strings.Contains(value, ":") { 147 | return fmt.Errorf("%s is not an IPv4 address", value) 148 | } 149 | _, _, err := net.ParseCIDR(value) 150 | if err != nil { 151 | return err 152 | } 153 | // Valid, add to the list 154 | *i = append(*i, value) 155 | return nil 156 | } 157 | -------------------------------------------------------------------------------- /src/core/api.go: -------------------------------------------------------------------------------- 1 | //go:build linux || windows || darwin || freebsd || netbsd || openbsd 2 | // +build linux windows darwin freebsd netbsd openbsd 3 | 4 | package main 5 | 6 | import ( 7 | "log" 8 | 9 | "github.com/gofiber/fiber/v2" 10 | "github.com/gofiber/websocket/v2" 11 | ) 12 | 13 | func web() { 14 | 15 | app := fiber.New() 16 | 17 | app.Get("/hello", func(c *fiber.Ctx) error { 18 | var cc = c 19 | println(cc) 20 | return c.SendString("Hello, World!") 21 | }) 22 | 23 | app.Use("/ws", func(c *fiber.Ctx) error { 24 | if websocket.IsWebSocketUpgrade(c) { 25 | c.Locals("allowed", true) 26 | return c.Next() 27 | } 28 | return fiber.ErrUpgradeRequired 29 | }) 30 | 31 | app.Get("/ws/:id", websocket.New(func(c *websocket.Conn) { 32 | // c.Locals is added to the *websocket.Conn 33 | log.Println(c.Locals("allowed")) // true 34 | log.Println(c.Params("id")) // 123 35 | log.Println(c.Query("v")) // 1.0 36 | log.Println(c.Cookies("session")) // "" 37 | 38 | // websocket.Conn bindings https://pkg.go.dev/github.com/fasthttp/websocket?tab=doc#pkg-index 39 | var ( 40 | mt int 41 | msg []byte 42 | err error 43 | ) 44 | for { 45 | if mt, msg, err = c.ReadMessage(); err != nil { 46 | log.Println("read:", err) 47 | break 48 | } 49 | log.Printf("recv: %s", msg) 50 | 51 | if err = c.WriteMessage(mt, msg); err != nil { 52 | log.Println("write:", err) 53 | break 54 | } 55 | } 56 | 57 | })) 58 | 59 | app.Listen(":33322") 60 | } 61 | -------------------------------------------------------------------------------- /src/core/freebsdapiwrapper.go: -------------------------------------------------------------------------------- 1 | // +build freebsd 2 | 3 | package main 4 | 5 | func (p *packiffer) setInterfaceFriendlyName() { 6 | 7 | } 8 | 9 | func displayFriendlyInterfaceName() { 10 | devices, err := pcap.FindAllDevs() 11 | if err != nil { 12 | log.Fatal(err) 13 | } 14 | displayDevices(devices) 15 | os.Exit(0) 16 | } 17 | 18 | func displayDevices(devices []pcap.Interface) { 19 | fmt.Println("Devices found:") 20 | fmt.Printf("\n") 21 | for _, device := range devices { 22 | fmt.Println("Name: ", device.Name) 23 | fmt.Println("Description: ", device.Description) 24 | fmt.Println("Devices addresses: ") 25 | for _, address := range device.Addresses { 26 | fmt.Println("\t- IP address: ", address.IP) 27 | fmt.Println("\t- Subnet mask: ", address.Netmask) 28 | } 29 | fmt.Printf("\n") 30 | } 31 | } 32 | 33 | func display() { 34 | displayFriendlyInterfaceName() 35 | } 36 | -------------------------------------------------------------------------------- /src/core/iptables.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package main 4 | 5 | import ( 6 | "bufio" 7 | "fmt" 8 | "log" 9 | "os" 10 | "os/exec" 11 | "time" 12 | ) 13 | 14 | func (p *packiffer) ipTables() { 15 | f, perr := os.Open(p.File) 16 | 17 | if perr != nil { 18 | log.Fatal(perr) 19 | } 20 | 21 | defer f.Close() 22 | 23 | scanner := bufio.NewScanner(f) 24 | 25 | for scanner.Scan() { 26 | 27 | fmt.Println(scanner.Text()) 28 | ipList = append(ipList, scanner.Text()) 29 | } 30 | 31 | if err := scanner.Err(); err != nil { 32 | log.Fatal(err) 33 | } 34 | 35 | for i := 0; i < len(ipList); i++ { 36 | 37 | c := exec.Command("iptables", "-A", "INPUT", "-s", ipList[i], "-j", "DROP") 38 | 39 | c.Stdin = os.Stdin 40 | c.Stdout = os.Stdout 41 | c.Stderr = os.Stderr 42 | 43 | err := c.Run() 44 | 45 | if err != nil { 46 | fmt.Printf("%s\n", err.Error()) 47 | os.Exit(1) 48 | } 49 | 50 | } 51 | 52 | println("Press ctrl + c to delete firewall and terminate program") 53 | 54 | for { 55 | time.Sleep(time.Second) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/core/linuxapiwrapper.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "log" 8 | "os" 9 | 10 | "github.com/google/gopacket/pcap" 11 | ) 12 | 13 | func (p *packiffer) setInterfaceFriendlyName() { 14 | 15 | } 16 | 17 | func displayFriendlyInterfaceName() { 18 | devices, err := pcap.FindAllDevs() 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | displayDevices(devices) 23 | os.Exit(0) 24 | } 25 | 26 | func displayDevices(devices []pcap.Interface) { 27 | fmt.Println("Devices found:") 28 | fmt.Printf("\n") 29 | for _, device := range devices { 30 | fmt.Println("Name: ", device.Name) 31 | fmt.Println("Description: ", device.Description) 32 | fmt.Println("Devices addresses: ") 33 | for _, address := range device.Addresses { 34 | fmt.Println("\t- IP address: ", address.IP) 35 | fmt.Println("\t- Subnet mask: ", address.Netmask) 36 | } 37 | fmt.Printf("\n") 38 | } 39 | } 40 | 41 | func display() { 42 | displayFriendlyInterfaceName() 43 | } 44 | -------------------------------------------------------------------------------- /src/core/macapiwrapper.go: -------------------------------------------------------------------------------- 1 | // +build darwin 2 | 3 | package main 4 | 5 | func (p *packiffer) setInterfaceFriendlyName() { 6 | 7 | } 8 | 9 | func displayFriendlyInterfaceName() { 10 | devices, err := pcap.FindAllDevs() 11 | if err != nil { 12 | log.Fatal(err) 13 | } 14 | displayDevices(devices) 15 | os.Exit(0) 16 | } 17 | 18 | func displayDevices(devices []pcap.Interface) { 19 | fmt.Println("Devices found:") 20 | fmt.Printf("\n") 21 | for _, device := range devices { 22 | fmt.Println("Name: ", device.Name) 23 | fmt.Println("Description: ", device.Description) 24 | fmt.Println("Devices addresses: ") 25 | for _, address := range device.Addresses { 26 | fmt.Println("\t- IP address: ", address.IP) 27 | fmt.Println("\t- Subnet mask: ", address.Netmask) 28 | } 29 | fmt.Printf("\n") 30 | } 31 | } 32 | 33 | func display() { 34 | displayFriendlyInterfaceName() 35 | } 36 | -------------------------------------------------------------------------------- /src/core/packetdump.go: -------------------------------------------------------------------------------- 1 | // +build linux windows darwin freebsd netbsd openbsd 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "sync" 8 | 9 | "github.com/google/gopacket" 10 | "github.com/google/gopacket/pcapgo" 11 | ) 12 | 13 | func (p *packiffer) sniffdumpPacket(packets gopacket.Packet, w *pcapgo.Writer, wg *sync.WaitGroup, mu *sync.Mutex) { 14 | defer wg.Done() 15 | mu.Lock() 16 | if err := w.WritePacket(packets.Metadata().CaptureInfo, packets.Data()); err != nil { 17 | fmt.Printf("pcap.WritePacket(): " + err.Error()) 18 | } 19 | mu.Unlock() 20 | } 21 | 22 | func (p *packiffer) transformdumpPacket(packets gopacket.Packet, w *pcapgo.Writer, wg *sync.WaitGroup, mu *sync.Mutex) { 23 | defer wg.Done() 24 | mu.Lock() 25 | if err := w.WritePacket(packets.Metadata().CaptureInfo, packets.Data()); err != nil { 26 | fmt.Printf("pcap.WritePacket(): " + err.Error()) 27 | } 28 | fmt.Printf("\033[2K\r%s%d", "packets transformed: ", packetCount) 29 | mu.Unlock() 30 | } 31 | -------------------------------------------------------------------------------- /src/core/packetfilter_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package main 4 | 5 | func (p *packiffer) firewall() { 6 | p.runBPF() 7 | // p.LinuxFirewall = "ipTables" 8 | // p.ipTables() 9 | } 10 | -------------------------------------------------------------------------------- /src/core/packetfilter_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package main 4 | 5 | import ( 6 | "bufio" 7 | "fmt" 8 | "log" 9 | "os" 10 | "os/exec" 11 | "time" 12 | ) 13 | 14 | type ipAddressList []string 15 | 16 | func (p *packiffer) firewall() { 17 | 18 | f, perr := os.Open(p.File) 19 | 20 | if perr != nil { 21 | log.Fatal(perr) 22 | } 23 | 24 | defer f.Close() 25 | 26 | scanner := bufio.NewScanner(f) 27 | 28 | for scanner.Scan() { 29 | 30 | fmt.Println(scanner.Text()) 31 | ipList = append(ipList, scanner.Text()) 32 | } 33 | 34 | if err := scanner.Err(); err != nil { 35 | log.Fatal(err) 36 | } 37 | 38 | for i := 0; i < len(ipList); i++ { 39 | 40 | c := exec.Command("netsh", "advfirewall", "firewall", "add", "rule", 41 | "name="+ipList[i], 42 | "dir="+"out", 43 | "action="+"block", 44 | "remoteip="+ipList[i], 45 | ) 46 | 47 | c.Stdin = os.Stdin 48 | c.Stdout = os.Stdout 49 | c.Stderr = os.Stderr 50 | 51 | err := c.Run() 52 | 53 | if err != nil { 54 | fmt.Printf("%s\n", err.Error()) 55 | os.Exit(1) 56 | } 57 | 58 | } 59 | 60 | println("Press ctrl + c to delete firewall and terminate program") 61 | 62 | for { 63 | time.Sleep(time.Second) 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/core/packetinject.go: -------------------------------------------------------------------------------- 1 | // +build linux windows darwin freebsd netbsd openbsd 2 | 3 | package main 4 | 5 | import ( 6 | "encoding/json" 7 | "fmt" 8 | "io/ioutil" 9 | "log" 10 | "net" 11 | "os" 12 | "reflect" 13 | 14 | "github.com/google/gopacket" 15 | "github.com/google/gopacket/layers" 16 | "github.com/google/gopacket/pcap" 17 | ) 18 | 19 | type Packet struct { 20 | Ethernet EthernetHeader `json:"ethernetLayer"` 21 | Ip IpHeader `json:"ipLayer"` 22 | Tcp TcpHeader `json:"tcpLayer"` 23 | Payload string `json:"payload"` 24 | } 25 | 26 | type EthernetHeader struct { 27 | SrcMAC string `json:"SrcMAC"` 28 | DstMAC string `json:"DstMAC"` 29 | } 30 | 31 | type IpHeader struct { 32 | SrcIP string `json:"SrcIP"` 33 | DstIP string `json:"DstIP"` 34 | } 35 | 36 | type TcpHeader struct { 37 | SrcPort int `json:"SrcPort"` 38 | DstPort int `json:"DstPort"` 39 | } 40 | 41 | func (p *packiffer) injectPacket() { 42 | p.handle, p.err = pcap.OpenLive(p.interfaceName, p.snapshotLen, p.promiscuous, p.timeout) 43 | if p.err != nil { 44 | log.Fatal(p.err) 45 | } 46 | defer p.handle.Close() 47 | 48 | if p.Raw { 49 | file, err := os.ReadFile(p.File) 50 | if err != nil { 51 | log.Fatal(err) 52 | os.Exit(0) 53 | } 54 | p.err = p.handle.WritePacketData(file) 55 | if p.err != nil { 56 | log.Fatal(p.err) 57 | } else { 58 | fmt.Println("Packet injected successfully.") 59 | } 60 | } 61 | if p.Constructed { 62 | 63 | jsonFile, err := os.Open(p.File) 64 | if err != nil { 65 | fmt.Println(err) 66 | } 67 | fmt.Println("Successfully Opened file") 68 | defer jsonFile.Close() 69 | 70 | packetValue, _ := ioutil.ReadAll(jsonFile) 71 | 72 | var packet Packet 73 | 74 | json.Unmarshal(packetValue, &packet) 75 | 76 | var ethernetLayer *layers.Ethernet 77 | var ipLayer *layers.IPv4 78 | var tcpLayer *layers.TCP 79 | 80 | if !reflect.ValueOf(packet.Ethernet).IsZero() { 81 | 82 | if !reflect.ValueOf(packet.Ethernet.SrcMAC).IsZero() && !reflect.ValueOf(packet.Ethernet.DstMAC).IsZero() { 83 | srcMAC, err := net.ParseMAC(packet.Ethernet.SrcMAC) 84 | if err != nil { 85 | fmt.Println(err) 86 | } 87 | dstMAC, err := net.ParseMAC(packet.Ethernet.SrcMAC) 88 | if err != nil { 89 | fmt.Println(err) 90 | } 91 | ethernetLayer = &layers.Ethernet{ 92 | SrcMAC: srcMAC, 93 | DstMAC: dstMAC, 94 | } 95 | } 96 | if !reflect.ValueOf(packet.Ethernet.SrcMAC).IsZero() && reflect.ValueOf(packet.Ethernet.DstMAC).IsZero() { 97 | srcMAC, err := net.ParseMAC(packet.Ethernet.SrcMAC) 98 | if err != nil { 99 | fmt.Println(err) 100 | } 101 | ethernetLayer = &layers.Ethernet{ 102 | SrcMAC: srcMAC, 103 | } 104 | } 105 | if reflect.ValueOf(packet.Ethernet.SrcMAC).IsZero() && !reflect.ValueOf(packet.Ethernet.DstMAC).IsZero() { 106 | dstMAC, err := net.ParseMAC(packet.Ethernet.SrcMAC) 107 | if err != nil { 108 | fmt.Println(err) 109 | } 110 | ethernetLayer = &layers.Ethernet{ 111 | DstMAC: dstMAC, 112 | } 113 | } 114 | } 115 | 116 | if !reflect.ValueOf(packet.Ip).IsZero() { 117 | 118 | if !reflect.ValueOf(packet.Ip.SrcIP).IsZero() && !reflect.ValueOf(packet.Ip.DstIP).IsZero() { 119 | ipLayer = &layers.IPv4{ 120 | SrcIP: net.ParseIP(packet.Ip.SrcIP), 121 | DstIP: net.ParseIP(packet.Ip.DstIP), 122 | } 123 | } 124 | if !reflect.ValueOf(packet.Ip.SrcIP).IsZero() && reflect.ValueOf(packet.Ip.DstIP).IsZero() { 125 | ipLayer = &layers.IPv4{ 126 | SrcIP: net.ParseIP(packet.Ip.SrcIP), 127 | } 128 | } 129 | if reflect.ValueOf(packet.Ip.SrcIP).IsZero() && !reflect.ValueOf(packet.Ip.DstIP).IsZero() { 130 | ipLayer = &layers.IPv4{ 131 | DstIP: net.ParseIP(packet.Ip.DstIP), 132 | } 133 | } 134 | } 135 | 136 | if !reflect.ValueOf(packet.Tcp).IsZero() { 137 | 138 | if !reflect.ValueOf(packet.Tcp.SrcPort).IsZero() && !reflect.ValueOf(packet.Tcp.DstPort).IsZero() { 139 | tcpLayer = &layers.TCP{ 140 | SrcPort: layers.TCPPort(packet.Tcp.SrcPort), 141 | DstPort: layers.TCPPort(packet.Tcp.DstPort), 142 | } 143 | } 144 | if !reflect.ValueOf(packet.Tcp.SrcPort).IsZero() && reflect.ValueOf(packet.Tcp.DstPort).IsZero() { 145 | tcpLayer = &layers.TCP{ 146 | SrcPort: layers.TCPPort(packet.Tcp.SrcPort), 147 | } 148 | } 149 | if reflect.ValueOf(packet.Tcp.SrcPort).IsZero() && !reflect.ValueOf(packet.Tcp.DstPort).IsZero() { 150 | tcpLayer = &layers.TCP{ 151 | DstPort: layers.TCPPort(packet.Tcp.DstPort), 152 | } 153 | } 154 | } 155 | 156 | p.buffer = gopacket.NewSerializeBuffer() 157 | rawBytes := []byte(packet.Payload) 158 | if !reflect.ValueOf(packet.Ethernet).IsZero() && 159 | !reflect.ValueOf(packet.Ip).IsZero() && 160 | !reflect.ValueOf(packet.Tcp).IsZero() { 161 | gopacket.SerializeLayers(p.buffer, p.options, 162 | ethernetLayer, 163 | ipLayer, 164 | tcpLayer, 165 | gopacket.Payload(rawBytes), 166 | ) 167 | } 168 | if !reflect.ValueOf(packet.Ethernet).IsZero() && 169 | !reflect.ValueOf(packet.Ip).IsZero() && 170 | reflect.ValueOf(packet.Tcp).IsZero() { 171 | gopacket.SerializeLayers(p.buffer, p.options, 172 | ethernetLayer, 173 | ipLayer, 174 | gopacket.Payload(rawBytes), 175 | ) 176 | } 177 | if !reflect.ValueOf(packet.Ethernet).IsZero() && 178 | reflect.ValueOf(packet.Ip).IsZero() && 179 | reflect.ValueOf(packet.Tcp).IsZero() { 180 | gopacket.SerializeLayers(p.buffer, p.options, 181 | ethernetLayer, 182 | gopacket.Payload(rawBytes), 183 | ) 184 | } 185 | outgoingPacket := p.buffer.Bytes() 186 | p.err = p.handle.WritePacketData(outgoingPacket) 187 | if p.err != nil { 188 | log.Fatal(p.err) 189 | } else { 190 | fmt.Println("Packet injected successfully.") 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /src/core/packetparser.go: -------------------------------------------------------------------------------- 1 | // +build linux windows darwin freebsd netbsd openbsd 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "strings" 8 | 9 | "github.com/google/gopacket" 10 | "github.com/google/gopacket/layers" 11 | ) 12 | 13 | func (p *packiffer) packetInfo(packet *gopacket.Packet) { 14 | 15 | fmt.Println("All packet layers:") 16 | for _, layer := range (*packet).Layers() { 17 | fmt.Println("- ", layer.LayerType()) 18 | } 19 | 20 | ethernetLayer := (*packet).Layer(layers.LayerTypeEthernet) 21 | if ethernetLayer != nil { 22 | fmt.Println("Ethernet layer detected.") 23 | ethernetPacket, _ := ethernetLayer.(*layers.Ethernet) 24 | fmt.Println("Source MAC: ", ethernetPacket.SrcMAC) 25 | fmt.Println("Destination MAC: ", ethernetPacket.DstMAC) 26 | fmt.Println("Ethernet type: ", ethernetPacket.EthernetType) 27 | fmt.Println() 28 | } 29 | 30 | arpLayer := (*packet).Layer(layers.LayerTypeARP) 31 | if arpLayer != nil { 32 | fmt.Println("Arp layer detected.") 33 | arp, _ := arpLayer.(*layers.ARP) 34 | fmt.Printf("AddrType: %d", arp.AddrType) 35 | fmt.Printf("Protocol: %d", arp.Protocol) 36 | fmt.Printf("SourceHwAddress: %d", arp.SourceHwAddress) 37 | fmt.Printf("SourceProtAddress: %d", arp.SourceProtAddress) 38 | fmt.Printf("DstHwAddress: %d", arp.DstHwAddress) 39 | fmt.Printf("DstProtAddress: %d", arp.DstProtAddress) 40 | fmt.Println() 41 | } 42 | 43 | ipv4Layer := (*packet).Layer(layers.LayerTypeIPv4) 44 | if ipv4Layer != nil { 45 | fmt.Println("IPv4 layer detected.") 46 | ipv4, _ := ipv4Layer.(*layers.IPv4) 47 | fmt.Printf("From %s to %s", ipv4.SrcIP, ipv4.DstIP) 48 | fmt.Println("Protocol: ", ipv4.Protocol) 49 | fmt.Println("TTL: ", ipv4.TTL) 50 | fmt.Println("TOS: ", ipv4.TOS) 51 | fmt.Println("IHL: ", ipv4.IHL) 52 | } 53 | 54 | tcpLayer := (*packet).Layer(layers.LayerTypeTCP) 55 | if tcpLayer != nil { 56 | fmt.Println("TCP layer detected.") 57 | tcp, _ := tcpLayer.(*layers.TCP) 58 | fmt.Printf("From port %d to %d", tcp.SrcPort, tcp.DstPort) 59 | fmt.Println("Sequence number: ", tcp.Seq) 60 | fmt.Println("ACK: ", tcp.Ack) 61 | } 62 | 63 | udpLayer := (*packet).Layer(layers.LayerTypeUDP) 64 | if udpLayer != nil { 65 | fmt.Println("UDP layer detected.") 66 | udp, _ := udpLayer.(*layers.UDP) 67 | fmt.Printf("From port %d to %d\n", udp.SrcPort, udp.DstPort) 68 | fmt.Println("Checksum number: ", udp.Checksum) 69 | fmt.Println() 70 | } 71 | 72 | applicationLayer := (*packet).ApplicationLayer() 73 | if applicationLayer != nil { 74 | fmt.Println("Application layer/Payload found.") 75 | fmt.Printf("%s\n", applicationLayer.Payload()) 76 | 77 | if strings.Contains(string(applicationLayer.Payload()), "HTTP") { 78 | fmt.Println("HTTP found!") 79 | } 80 | if strings.Contains(string(applicationLayer.Payload()), "FTP") { 81 | fmt.Println("FTP found!") 82 | } 83 | } 84 | 85 | if err := (*packet).ErrorLayer(); err != nil { 86 | fmt.Println("Error decoding some part of the packet:", err) 87 | } 88 | 89 | fmt.Println("Press any key to inspect next packet") 90 | var first string 91 | fmt.Scanln(&first) 92 | } 93 | -------------------------------------------------------------------------------- /src/core/packetsniff.go: -------------------------------------------------------------------------------- 1 | // +build linux windows darwin freebsd netbsd openbsd 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "log" 8 | "os" 9 | "runtime" 10 | "strings" 11 | "sync" 12 | "sync/atomic" 13 | "time" 14 | 15 | "github.com/google/gopacket" 16 | "github.com/google/gopacket/layers" 17 | "github.com/google/gopacket/pcap" 18 | "github.com/google/gopacket/pcapgo" 19 | ) 20 | 21 | func (p *packiffer) openTransformPcap() { 22 | p.handle, p.err = pcap.OpenOffline(p.input) 23 | if p.err != nil { 24 | log.Fatal(p.err) 25 | } 26 | defer p.handle.Close() 27 | if transformFilterFlag { 28 | p.filterPacket() 29 | } 30 | packetCount = 0 31 | var f *os.File = nil 32 | p.createTransformPcap(&f) 33 | w := pcapgo.NewWriter(f) 34 | w.WriteFileHeader(snapshotLen, layers.LinkTypeEthernet) 35 | defer f.Close() 36 | var wg sync.WaitGroup 37 | var mu sync.Mutex 38 | packetSource := gopacket.NewPacketSource(p.handle, p.handle.LinkType()) 39 | for packet := range packetSource.Packets() { 40 | atomic.AddInt64(&packetCount, 1) 41 | wg.Add(1) 42 | go p.transformdumpPacket(packet, w, &wg, &mu) 43 | if packetCount > int64(p.limit) { 44 | break 45 | } 46 | } 47 | wg.Wait() 48 | } 49 | 50 | func (p *packiffer) openLivePcap() { 51 | if runtime.GOOS == "windows" { 52 | p.setInterfaceFriendlyName() 53 | } 54 | p.handle, p.err = pcap.OpenLive(p.interfaceName, p.snapshotLen, p.promiscuous, p.timeout) 55 | if p.err != nil { 56 | log.Fatal(p.err) 57 | } 58 | defer p.handle.Close() 59 | if sniffFilterFlag { 60 | p.filterPacket() 61 | } 62 | packetCount = 0 63 | var f *os.File = nil 64 | p.createSniffPcap(&f) 65 | w := pcapgo.NewWriter(f) 66 | if err := w.WriteFileHeader(snapshotLen, layers.LinkTypeEthernet); err != nil { 67 | fmt.Print("pcap.WriteFileHeader(): " + err.Error()) 68 | } 69 | defer f.Close() 70 | go displayPacketCount() 71 | var wg sync.WaitGroup 72 | var mu sync.Mutex 73 | if snifflimitFlag { 74 | packets := gopacket.NewPacketSource(p.handle, p.handle.LinkType()) 75 | for packet := range packets.Packets() { 76 | atomic.AddInt64(&packetCount, 1) 77 | wg.Add(1) 78 | go p.sniffdumpPacket(packet, w, &wg, &mu) 79 | if packetCount > 10000 { 80 | break 81 | } 82 | } 83 | wg.Wait() 84 | } else { 85 | packets := gopacket.NewPacketSource(p.handle, p.handle.LinkType()) 86 | for packet := range packets.Packets() { 87 | atomic.AddInt64(&packetCount, 1) 88 | wg.Add(1) 89 | go p.sniffdumpPacket(packet, w, &wg, &mu) 90 | if packetCount > int64(p.limit) { 91 | break 92 | } 93 | } 94 | wg.Wait() 95 | } 96 | } 97 | 98 | func (p *packiffer) createSniffPcap(f **os.File) { 99 | var err error 100 | if sniffoutputdirectoryFlag && sniffoutputfilenameFlag { 101 | *f, err = os.Create(p.outputDirectory + "/" + p.outputFileName + ".pcap") 102 | if err != nil { 103 | fmt.Println("error in creating pcap file") 104 | os.Exit(0) 105 | } 106 | fmt.Println("packets dump in: " + p.outputDirectory + "/" + p.outputFileName + ".pcap") 107 | } 108 | if !sniffoutputdirectoryFlag && sniffoutputfilenameFlag { 109 | *f, err = os.Create(p.outputFileName + ".pcap") 110 | if err != nil { 111 | fmt.Println("error in creating pcap file") 112 | os.Exit(0) 113 | } 114 | fmt.Println("packets dump in: " + p.outputFileName + ".pcap") 115 | } 116 | if sniffoutputdirectoryFlag && !sniffoutputfilenameFlag { 117 | if runtime.GOOS == "windows" { 118 | *f, err = os.Create(p.outputDirectory + "/" + strings.TrimSpace(p.interfaceFriendlyName) + ".pcap") 119 | if err != nil { 120 | fmt.Println("error in creating pcap file") 121 | os.Exit(0) 122 | } 123 | fmt.Println("packets dump in: " + p.outputDirectory + "/" + strings.TrimSpace(p.interfaceFriendlyName) + ".pcap") 124 | } else { 125 | *f, err = os.Create(p.outputDirectory + "/" + p.interfaceName + ".pcap") 126 | if err != nil { 127 | fmt.Println("error in creating pcap file") 128 | os.Exit(0) 129 | } 130 | fmt.Println("packets dump in: " + p.outputDirectory + "/" + p.interfaceName + ".pcap") 131 | } 132 | } 133 | if !sniffoutputdirectoryFlag && !sniffoutputfilenameFlag { 134 | if runtime.GOOS == "windows" { 135 | *f, err = os.Create(strings.TrimSpace(p.interfaceFriendlyName) + ".pcap") 136 | if err != nil { 137 | fmt.Println("error in creating pcap file") 138 | os.Exit(0) 139 | } 140 | fmt.Println("packets dump in: " + strings.TrimSpace(p.interfaceFriendlyName) + ".pcap") 141 | } else { 142 | *f, err = os.Create(p.interfaceName + ".pcap") 143 | if err != nil { 144 | fmt.Println("error in creating pcap file") 145 | os.Exit(0) 146 | } 147 | fmt.Println("packets dump in: " + p.interfaceName + ".pcap") 148 | } 149 | } 150 | } 151 | 152 | func (p *packiffer) createTransformPcap(f **os.File) { 153 | var err error 154 | if transformoutputdirectoryFlag && transformoutputfilenameFlag { 155 | *f, err = os.Create(p.outputDirectory + "/" + p.outputFileName + ".pcap") 156 | if err != nil { 157 | fmt.Println("error in creating pcap file") 158 | os.Exit(0) 159 | } 160 | fmt.Println("packets dump in: " + p.outputDirectory + "/" + p.outputFileName + ".pcap") 161 | } 162 | if !transformoutputdirectoryFlag && transformoutputfilenameFlag { 163 | *f, err = os.Create(p.outputFileName + ".pcap") 164 | if err != nil { 165 | fmt.Println("error in creating pcap file") 166 | os.Exit(0) 167 | } 168 | fmt.Println("packets dump in: " + p.outputFileName + ".pcap") 169 | } 170 | if transformoutputdirectoryFlag && !transformoutputfilenameFlag { 171 | dt := time.Now() 172 | *f, err = os.Create(p.outputDirectory + "/" + dt.Format("02-11-1979-17:06:06") + ".pcap") 173 | if err != nil { 174 | fmt.Println("error in creating pcap file") 175 | os.Exit(0) 176 | } 177 | fmt.Println("packets dump in: " + p.outputDirectory + "/" + dt.Format("02-11-1979-17:06:06") + ".pcap") 178 | } 179 | if !transformoutputdirectoryFlag && !transformoutputfilenameFlag { 180 | dt := time.Now() 181 | *f, err = os.Create(dt.Format("02-11-1979-17:06:06") + ".pcap") 182 | if err != nil { 183 | fmt.Println("error in creating pcap file") 184 | os.Exit(0) 185 | } 186 | fmt.Println("packets dump in: " + dt.Format("02-11-1979-17:06:06") + ".pcap") 187 | } 188 | } 189 | 190 | func displayPacketCount() { 191 | ticker := time.Tick(time.Second) 192 | for { 193 | <-ticker 194 | fmt.Printf("\033[2K\r%s%d", "packets sniffed: ", packetCount) 195 | } 196 | } 197 | 198 | func (p *packiffer) filterPacket() { 199 | p.err = p.handle.SetBPFFilter(p.filter) 200 | if p.err != nil { 201 | log.Fatal(p.err) 202 | } 203 | } 204 | 205 | func (p *packiffer) openInputPcap() { 206 | p.handle, p.err = pcap.OpenOffline(p.input) 207 | if p.err != nil { 208 | log.Fatal(p.err) 209 | } 210 | defer p.handle.Close() 211 | 212 | packetSource := gopacket.NewPacketSource(p.handle, p.handle.LinkType()) 213 | for packet := range packetSource.Packets() { 214 | p.packetInfo(&packet) 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /src/core/packiffer.go: -------------------------------------------------------------------------------- 1 | // +build linux windows darwin freebsd netbsd openbsd 2 | 3 | package main 4 | 5 | import ( 6 | "flag" 7 | "fmt" 8 | "io" 9 | "log" 10 | "os" 11 | "os/exec" 12 | "os/signal" 13 | "runtime" 14 | "strings" 15 | "syscall" 16 | "time" 17 | 18 | "github.com/google/gopacket" 19 | "github.com/google/gopacket/pcap" 20 | ) 21 | 22 | var snapshotLen uint32 23 | 24 | type packiffer struct { 25 | interfaceName string 26 | interfaceFriendlyName string 27 | promiscuous bool 28 | interfaceIndex int 29 | filter string 30 | socketDescriptor int 31 | input string 32 | outputFileName string 33 | outputDirectory string 34 | limit int 35 | device bool 36 | snapshotLen int32 37 | help bool 38 | err error 39 | timeout time.Duration 40 | handle *pcap.Handle 41 | mode string 42 | Raw bool 43 | Constructed bool 44 | File string 45 | buffer gopacket.SerializeBuffer 46 | options gopacket.SerializeOptions 47 | LinuxFirewall string 48 | } 49 | 50 | var sniffInterfaceNameFlag bool 51 | var sniffPromiscuousFlag bool 52 | var sniffFilterFlag bool 53 | var sniffoutputdirectoryFlag bool 54 | var sniffoutputfilenameFlag bool 55 | var sniffsnapshotlengthFlag bool 56 | var snifftimeoutFlag bool 57 | var snifflimitFlag bool 58 | 59 | var transformInterfaceNameFlag bool 60 | var transformFilterFlag bool 61 | var transformInputFlag bool 62 | var transformoutputdirectoryFlag bool 63 | var transformoutputfilenameFlag bool 64 | var transformlimitFlag bool 65 | 66 | var inspectInputFlag bool 67 | var inspectFilterFlag bool 68 | var inspectlimitFlag bool 69 | 70 | var injectInterface bool 71 | var injectRaw bool 72 | var injectConstruct bool 73 | var injectFile bool 74 | 75 | var firewallInterface bool 76 | var firewallFile bool 77 | 78 | var helpFlag bool 79 | var deviceFlag bool 80 | 81 | var packetCount int64 82 | var httpCount int64 83 | var tcpCount int64 84 | var udpCount int64 85 | var ipCount int64 86 | var arpCount int64 87 | var ethCount int64 88 | var otherCount int64 89 | var dumpPackets bool 90 | var displayPackets bool 91 | var displayChart bool 92 | var packetLimit int 93 | 94 | var ipList ipAddressList 95 | 96 | func isFlagPassed(name string, FlagSet *flag.FlagSet) bool { 97 | found := false 98 | FlagSet.Visit(func(f *flag.Flag) { 99 | if f.Name == name { 100 | found = true 101 | } 102 | }) 103 | return found 104 | } 105 | 106 | func (p *packiffer) ctrlCHandler() { 107 | c := make(chan os.Signal) 108 | signal.Notify(c, os.Interrupt, syscall.SIGTERM) 109 | go func() { 110 | <-c 111 | fmt.Println("\r- Ctrl+C pressed in Terminal") 112 | if p.mode == "firewall" && runtime.GOOS == "windows" { 113 | 114 | for i := 0; i < len(ipList); i++ { 115 | 116 | cmd := exec.Command("netsh", "advfirewall", "firewall", "delete", "rule", "name="+ipList[i]) 117 | 118 | cmd.Stdin = os.Stdin 119 | cmd.Stdout = os.Stdout 120 | cmd.Stderr = os.Stderr 121 | 122 | errs := cmd.Run() 123 | 124 | if errs != nil { 125 | fmt.Printf("%s\n", errs.Error()) 126 | os.Exit(1) 127 | } 128 | 129 | } 130 | } 131 | if p.mode == "firewall" && runtime.GOOS == "linux" && p.LinuxFirewall == "ipTables" { 132 | 133 | for i := 0; i < len(ipList); i++ { 134 | 135 | cmd := exec.Command("iptables", "-D", "INPUT", "-s", ipList[i], "-j", "DROP") 136 | 137 | cmd.Stdin = os.Stdin 138 | cmd.Stdout = os.Stdout 139 | cmd.Stderr = os.Stderr 140 | 141 | errs := cmd.Run() 142 | 143 | if errs != nil { 144 | fmt.Printf("%s\n", errs.Error()) 145 | os.Exit(1) 146 | } 147 | 148 | } 149 | } 150 | os.Exit(0) 151 | }() 152 | } 153 | 154 | func showhelp() { 155 | 156 | } 157 | 158 | func checkSniffFlagsPassed(flag *flag.FlagSet) { 159 | sniffInterfaceNameFlag = isFlagPassed("i", flag) 160 | sniffPromiscuousFlag = isFlagPassed("p", flag) 161 | sniffFilterFlag = isFlagPassed("f", flag) 162 | sniffoutputdirectoryFlag = isFlagPassed("od", flag) 163 | sniffoutputfilenameFlag = isFlagPassed("of", flag) 164 | sniffsnapshotlengthFlag = isFlagPassed("sl", flag) 165 | snifftimeoutFlag = isFlagPassed("t", flag) 166 | snifflimitFlag = isFlagPassed("c", flag) 167 | } 168 | 169 | func checkTransformFlagsPassed(flag *flag.FlagSet) { 170 | transformFilterFlag = isFlagPassed("f", flag) 171 | transformInputFlag = isFlagPassed("in", flag) 172 | transformoutputdirectoryFlag = isFlagPassed("od", flag) 173 | transformoutputfilenameFlag = isFlagPassed("of", flag) 174 | transformlimitFlag = isFlagPassed("c", flag) 175 | } 176 | 177 | func checkInspectFlagsPassed(flag *flag.FlagSet) { 178 | inspectInputFlag = isFlagPassed("in", flag) 179 | inspectFilterFlag = isFlagPassed("f", flag) 180 | inspectlimitFlag = isFlagPassed("c", flag) 181 | } 182 | 183 | func checkInjectFlagsPassed(flag *flag.FlagSet) { 184 | injectInterface = isFlagPassed("i", flag) 185 | injectRaw = isFlagPassed("ir", flag) 186 | injectConstruct = isFlagPassed("ic", flag) 187 | injectFile = isFlagPassed("f", flag) 188 | } 189 | 190 | func checkFirewallFlagsPassed(flag *flag.FlagSet) { 191 | firewallInterface = isFlagPassed("i", flag) 192 | firewallFile = isFlagPassed("f", flag) 193 | } 194 | 195 | func getFlagsValue() *packiffer { 196 | 197 | sniffCommand := flag.NewFlagSet("sniff", flag.ExitOnError) 198 | sniffInterfaceName := sniffCommand.String("i", "eth0", "Specify interface name. Default is eth0") 199 | sniffPromiscuous := sniffCommand.Bool("p", false, "Specify promiscuous mode. Default is false") 200 | sniffFilter := sniffCommand.String("f", "all", "Specify filter query. Default is all") 201 | sniffoutputdirectory := sniffCommand.String("od", "packiffer", "Specify output directory. Default is packiffer directory") 202 | sniffoutputfilename := sniffCommand.String("of", "interface", "Specify output file name. Default is interface name") 203 | sniffsnapshotlength := sniffCommand.Int("sl", 1024, "Specify Snapshot Lenght. Default is 2014") 204 | snifftimeout := sniffCommand.Int("t", 30, "limit sniffing timeout. Default is 30 seconds") 205 | snifflimit := sniffCommand.Int("c", 10000, "Limit count of packets to sniff. Default is 10000") 206 | 207 | transformCommand := flag.NewFlagSet("transform", flag.ExitOnError) 208 | transformFilter := transformCommand.String("f", "all", "Specify filter query. Default is all") 209 | transformInput := transformCommand.String("in", "", "Specify input pcap file") 210 | transformoutputdirectory := transformCommand.String("od", "packiffer", "Specify output directory. Default is packiffer directory") 211 | transformoutputfilename := transformCommand.String("of", "interface", "Specify output file name. Default is interface name") 212 | transformlimit := transformCommand.Int("c", 10000, "Limit count of packets to sniff. Default is 10000") 213 | 214 | inspectCommand := flag.NewFlagSet("inspect", flag.ExitOnError) 215 | inspectInput := inspectCommand.String("in", "", "Specify input pcap file") 216 | inspectFilter := inspectCommand.String("f", "all", "Specify filter query. Default is all") 217 | inspectlimit := inspectCommand.Int("c", 10000, "Limit count of packets to sniff. Default is 10000") 218 | 219 | injectCommand := flag.NewFlagSet("inject", flag.ExitOnError) 220 | injectInterface := injectCommand.String("i", "eth0", "Specify interface name. Default is eth0") 221 | injectRaw := injectCommand.Bool("ir", false, "Specify Raw Packet Inject. Default is false") 222 | injectConstruct := injectCommand.Bool("ic", false, "Specify Constructed Packet Inject. Default is False") 223 | injectFile := injectCommand.String("f", "inject.txt", "Specify Path to packet file. Default is inject.txt") 224 | 225 | firewallCommand := flag.NewFlagSet("firewall", flag.ExitOnError) 226 | fireWallInterface := firewallCommand.String("i", "eth0", "Specify interface name. Default is eth0") 227 | fireWallFile := firewallCommand.String("f", "firewall.txt", "Specify Path to firewall file. Default is firewall.txt") 228 | 229 | help := flag.Bool("h", false, "Specify help display. Default is false") 230 | device := flag.Bool("d", false, "Specify devices display. Default is false") 231 | 232 | flag.Parse() 233 | 234 | if *help { 235 | showhelp() 236 | os.Exit(0) 237 | } 238 | 239 | if *device { 240 | display() 241 | os.Exit(0) 242 | } 243 | 244 | if len(os.Args) < 1 { 245 | showhelp() 246 | os.Exit(0) 247 | } 248 | 249 | switch os.Args[1] { 250 | 251 | case "sniff": 252 | sniffCommand.Parse(os.Args[2:]) 253 | packetLimit = *snifflimit 254 | checkSniffFlagsPassed(sniffCommand) 255 | return &packiffer{ 256 | interfaceName: *sniffInterfaceName, 257 | promiscuous: *sniffPromiscuous, 258 | filter: *sniffFilter, 259 | outputDirectory: *sniffoutputdirectory, 260 | outputFileName: *sniffoutputfilename, 261 | device: *device, 262 | snapshotLen: int32(*sniffsnapshotlength), 263 | timeout: time.Duration(*snifftimeout) * time.Second, 264 | limit: *snifflimit, 265 | mode: "sniff", 266 | help: *help} 267 | case "transform": 268 | transformCommand.Parse(os.Args[2:]) 269 | packetLimit = *transformlimit 270 | checkTransformFlagsPassed(transformCommand) 271 | return &packiffer{ 272 | filter: *transformFilter, 273 | outputDirectory: *transformoutputdirectory, 274 | outputFileName: *transformoutputfilename, 275 | device: *device, 276 | limit: *transformlimit, 277 | mode: "transform", 278 | input: *transformInput, 279 | help: *help} 280 | 281 | case "inspect": 282 | inspectCommand.Parse(os.Args[2:]) 283 | checkInspectFlagsPassed(inspectCommand) 284 | return &packiffer{ 285 | filter: *inspectFilter, 286 | device: *device, 287 | limit: *inspectlimit, 288 | mode: "inspect", 289 | input: *inspectInput, 290 | help: *help} 291 | 292 | case "inject": 293 | injectCommand.Parse(os.Args[2:]) 294 | checkInjectFlagsPassed(injectCommand) 295 | return &packiffer{ 296 | interfaceName: *injectInterface, 297 | Raw: *injectRaw, 298 | Constructed: *injectConstruct, 299 | File: *injectFile, 300 | device: *device, 301 | mode: "inject", 302 | help: *help} 303 | 304 | case "firewall": 305 | injectCommand.Parse(os.Args[2:]) 306 | checkFirewallFlagsPassed(firewallCommand) 307 | return &packiffer{ 308 | interfaceName: *fireWallInterface, 309 | File: *fireWallFile, 310 | device: *device, 311 | mode: "firewall", 312 | help: *help} 313 | 314 | case "web": 315 | web() 316 | 317 | default: 318 | showhelp() 319 | os.Exit(0) 320 | } 321 | return nil 322 | } 323 | 324 | func (p *packiffer) pcap(mode string) { 325 | if mode == "sniff" { 326 | fmt.Printf("\nStarting Packiffer in sniffing mode\n") 327 | p.openLivePcap() 328 | } 329 | if mode == "transform" { 330 | fmt.Printf("\nStarting Packiffer in transform mode\n") 331 | p.openTransformPcap() 332 | } 333 | if mode == "inspect" { 334 | fmt.Printf("\nStarting Packiffer in inspect mode\n") 335 | p.openInputPcap() 336 | } 337 | if mode == "inject" { 338 | fmt.Printf("\nStarting Packiffer in inject mode\n") 339 | p.injectPacket() 340 | } 341 | if mode == "firewall" { 342 | fmt.Printf("\nStarting Packiffer in firewall mode\n") 343 | p.firewall() 344 | } 345 | } 346 | 347 | func exists(path string) (bool, error) { 348 | _, err := os.Stat(path) 349 | if err == nil { 350 | return true, nil 351 | } 352 | if os.IsNotExist(err) { 353 | return false, nil 354 | } 355 | return false, err 356 | } 357 | 358 | func RunCommandCh(stdoutCh chan<- string, cutset string, command string, flags ...string) error { 359 | cmd := exec.Command(command, flags...) 360 | 361 | output, err := cmd.StdoutPipe() 362 | if err != nil { 363 | return fmt.Errorf("RunCommand: cmd.StdoutPipe(): %v", err) 364 | } 365 | 366 | if err := cmd.Start(); err != nil { 367 | return fmt.Errorf("RunCommand: cmd.Start(): %v", err) 368 | } 369 | 370 | go func() { 371 | defer close(stdoutCh) 372 | for { 373 | buf := make([]byte, 1024) 374 | n, err := output.Read(buf) 375 | if err != nil { 376 | if err != io.EOF { 377 | log.Fatal(err) 378 | } 379 | if n == 0 { 380 | break 381 | } 382 | } 383 | text := strings.TrimSpace(string(buf[:n])) 384 | for { 385 | // Take the index of any of the given cutset 386 | n := strings.IndexAny(text, cutset) 387 | if n == -1 { 388 | // If not found, but still have data, send it 389 | if len(text) > 0 { 390 | stdoutCh <- text 391 | } 392 | break 393 | } 394 | // Send data up to the found cutset 395 | stdoutCh <- text[:n] 396 | // If cutset is last element, stop there. 397 | if n == len(text) { 398 | break 399 | } 400 | // Shift the text and start again. 401 | text = text[n+1:] 402 | } 403 | } 404 | }() 405 | 406 | if err := cmd.Wait(); err != nil { 407 | return fmt.Errorf("RunCommand: cmd.Wait(): %v", err) 408 | } 409 | return nil 410 | } 411 | 412 | func main() { 413 | 414 | p := getFlagsValue() 415 | 416 | p.ctrlCHandler() 417 | 418 | if p == nil { 419 | os.Exit(0) 420 | } 421 | 422 | flag.Usage = func() { 423 | showhelp() 424 | } 425 | 426 | if helpFlag { 427 | showhelp() 428 | os.Exit(0) 429 | } 430 | 431 | p.pcap(p.mode) 432 | 433 | os.Exit(0) 434 | } 435 | -------------------------------------------------------------------------------- /src/core/windowsapiwrapper.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "log" 8 | "net" 9 | "os" 10 | "strings" 11 | 12 | "github.com/google/gopacket/pcap" 13 | ) 14 | 15 | type Interface struct { 16 | Name string 17 | Description string 18 | Flags uint32 19 | Addresses []pcap.InterfaceAddress 20 | FriendlyName string 21 | } 22 | 23 | type InterfaceAddress struct { 24 | IP net.IP 25 | Netmask net.IPMask 26 | Broadaddr net.IP 27 | P2P net.IP 28 | } 29 | 30 | var deviceListGlobal []Interface 31 | 32 | func (p *packiffer) setInterfaceFriendlyName() { 33 | devices, err := pcap.FindAllDevs() 34 | if err != nil { 35 | log.Fatal(err) 36 | } 37 | var deviceList = compare(devices) 38 | deviceListGlobal = deviceList 39 | for _, element := range deviceListGlobal { 40 | if element.Name == p.interfaceName { 41 | p.interfaceFriendlyName = element.FriendlyName 42 | } 43 | } 44 | } 45 | 46 | func displayFriendlyInterfaceName() { 47 | devices, err := pcap.FindAllDevs() 48 | if err != nil { 49 | log.Fatal(err) 50 | } 51 | var deviceList = compare(devices) 52 | deviceListGlobal = deviceList 53 | displayDevices(deviceList) 54 | os.Exit(0) 55 | } 56 | 57 | func displayDevices(devices []Interface) { 58 | fmt.Println("Devices found:") 59 | fmt.Printf("\n") 60 | for _, device := range devices { 61 | fmt.Println("Name: ", device.Name) 62 | fmt.Println("FriendlyName: ", device.FriendlyName) 63 | fmt.Println("Description: ", device.Description) 64 | fmt.Println("Devices addresses: ") 65 | for _, address := range device.Addresses { 66 | fmt.Println("\t- IP address: ", address.IP) 67 | fmt.Println("\t- Subnet mask: ", address.Netmask) 68 | } 69 | fmt.Printf("\n") 70 | } 71 | } 72 | 73 | func compare(devices []pcap.Interface) []Interface { 74 | interfaceList := []Interface{} 75 | var mac = getmac() 76 | var ni = networkInterfaceList() 77 | for key, element := range mac { 78 | for _, d := range ni { 79 | if strings.ReplaceAll(strings.ToUpper(d.HardwareAddr.String()), ":", "-") == key { 80 | for _, device := range devices { 81 | if strings.Contains(device.Name, match(element[0])) { 82 | var interfaceElement = Interface{ 83 | Name: device.Name, 84 | FriendlyName: d.Name, 85 | Description: device.Description, 86 | Flags: device.Flags, 87 | Addresses: device.Addresses, 88 | } 89 | interfaceList = append(interfaceList, interfaceElement) 90 | } 91 | } 92 | } 93 | } 94 | } 95 | return interfaceList 96 | } 97 | 98 | func match(s string) string { 99 | i := strings.Index(s, "{") 100 | if i >= 0 { 101 | j := strings.Index(s, "}") 102 | if j >= 0 { 103 | return s[i+1 : j] 104 | } 105 | } 106 | return "" 107 | } 108 | 109 | func getmac() map[string][]string { 110 | 111 | ch := make(chan string) 112 | go func() { 113 | err := RunCommandCh(ch, "\r\n", "getmac") 114 | if err != nil { 115 | log.Fatal(err) 116 | } 117 | }() 118 | 119 | var getmacarray []string 120 | 121 | for v := range ch { 122 | if strings.Count(v, "-") == 5 { 123 | getmacarray = append(getmacarray, v) 124 | } 125 | if strings.Contains(v, "\\Device") { 126 | getmacarray = append(getmacarray, v) 127 | } 128 | } 129 | 130 | x := make(map[string][]string) 131 | 132 | for i := 0; i <= len(getmacarray)-1; { 133 | if i+1 <= len(getmacarray)-1 && strings.Contains(getmacarray[i+1], "\\Device") { 134 | x[getmacarray[i]] = append(x[getmacarray[i]], getmacarray[i+1]) 135 | } 136 | i = i + 1 137 | } 138 | 139 | return x 140 | } 141 | 142 | func networkInterfaceList() []net.Interface { 143 | ifaces, err := net.Interfaces() 144 | if err != nil { 145 | fmt.Println(fmt.Errorf("localAddresses: %+v", err.Error())) 146 | return nil 147 | } 148 | return ifaces 149 | } 150 | 151 | func display() { 152 | displayFriendlyInterfaceName() 153 | } 154 | -------------------------------------------------------------------------------- /src/ebpf/xdp_block_address.c: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | #include "bpf_helpers.h" 4 | 5 | #define MAX_RULES 16 6 | 7 | // Ethernet header 8 | struct ethhdr { 9 | __u8 h_dest[6]; 10 | __u8 h_source[6]; 11 | __u16 h_proto; 12 | } __attribute__((packed)); 13 | 14 | // IPv4 header 15 | struct iphdr { 16 | __u8 ihl : 4; 17 | __u8 version : 4; 18 | __u8 tos; 19 | __u16 tot_len; 20 | __u16 id; 21 | __u16 frag_off; 22 | __u8 ttl; 23 | __u8 protocol; 24 | __u16 check; 25 | __u32 saddr; 26 | __u32 daddr; 27 | } __attribute__((packed)); 28 | 29 | // TCP header 30 | struct tcphdr { 31 | __u16 source; 32 | __u16 dest; 33 | __u32 seq; 34 | __u32 ack_seq; 35 | __u16 res1:4, 36 | doff:4, 37 | fin:1, 38 | syn:1, 39 | rst:1, 40 | psh:1, 41 | ack:1, 42 | urg:1, 43 | ece:1, 44 | cwr:1; 45 | __u16 window; 46 | __u16 check; 47 | __u16 urg_ptr; 48 | } __attribute__((packed)); 49 | 50 | // UDP header 51 | struct udphdr { 52 | __u16 source; 53 | __u16 dest; 54 | __u16 len; 55 | __u16 check; 56 | }; 57 | 58 | BPF_MAP_DEF(matches) = { 59 | .map_type = BPF_MAP_TYPE_PERCPU_ARRAY, 60 | .key_size = sizeof(__u32), 61 | .value_size = sizeof(__u64), 62 | .max_entries = MAX_RULES, 63 | }; 64 | BPF_MAP_ADD(matches); 65 | 66 | 67 | BPF_MAP_DEF(blacklist) = { 68 | .map_type = BPF_MAP_TYPE_LPM_TRIE, 69 | .key_size = sizeof(__u64), 70 | .value_size = sizeof(__u32), 71 | .max_entries = MAX_RULES, 72 | }; 73 | BPF_MAP_ADD(blacklist); 74 | 75 | // XDP program // 76 | SEC("xdp") 77 | int firewall(struct xdp_md *ctx) { 78 | 79 | void *data_end = (void *)(long)ctx->data_end; 80 | void *data = (void *)(long)ctx->data; 81 | 82 | struct ethhdr *ether = data; 83 | if (data + sizeof(*ether) > data_end) { 84 | // Malformed Ethernet header 85 | return XDP_ABORTED; 86 | } 87 | 88 | if (ether->h_proto != 0x08U) { // htons(ETH_P_IP) -> 0x08U 89 | // Non IPv4 traffic 90 | return XDP_PASS; 91 | } 92 | 93 | data += sizeof(*ether); 94 | struct iphdr *ip = data; 95 | if (data + sizeof(*ip) > data_end) { 96 | // Malformed IPv4 header 97 | return XDP_ABORTED; 98 | } 99 | 100 | // if (ip->protocol == 0x06) // htons(IPPROTO_TCP) -> 0x06 101 | // { 102 | 103 | // data += sizeof(*ip); 104 | // struct tcphdr *tcp = data; 105 | // if (data + sizeof(*tcp) > data_end) { 106 | // // Malformed TCP header 107 | // return XDP_ABORTED; 108 | // } 109 | 110 | 111 | 112 | // } 113 | 114 | struct { 115 | __u32 prefixlen; 116 | __u32 saddr; 117 | } key; 118 | 119 | key.prefixlen = 32; 120 | key.saddr = ip->saddr; 121 | 122 | __u64 *rule_idx = bpf_map_lookup_elem(&blacklist, &key); 123 | if (rule_idx) { 124 | __u32 index = *(__u32*)rule_idx; 125 | __u64 *counter = bpf_map_lookup_elem(&matches, &index); 126 | if (counter) { 127 | (*counter)++; 128 | } 129 | return XDP_DROP; 130 | } 131 | 132 | return XDP_PASS; 133 | 134 | } 135 | 136 | char _license[] SEC("license") = "GPLv2"; -------------------------------------------------------------------------------- /src/ebpf/xdp_block_address.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use aya_bpf::{ 5 | bindings::xdp_action, 6 | macros::{map, xdp}, 7 | maps::{HashMap, PerfEventArray}, 8 | programs::XdpContext, 9 | }; 10 | 11 | use core::mem; 12 | use memoffset::offset_of; 13 | use myapp_common::PacketLog; 14 | 15 | mod bindings; 16 | use bindings::{ethhdr, iphdr}; 17 | 18 | #[panic_handler] 19 | fn panic(_info: &core::panic::PanicInfo) -> ! { 20 | unreachable!() 21 | } 22 | 23 | #[map(name = "EVENTS")] 24 | static mut EVENTS: PerfEventArray = 25 | PerfEventArray::::with_max_entries(1024, 0); 26 | 27 | #[map(name = "BLOCKLIST")] 28 | static mut BLOCKLIST: HashMap = HashMap::::with_max_entries(1024, 0); 29 | 30 | #[xdp] 31 | pub fn xdp_firewall(ctx: XdpContext) -> u32 { 32 | match try_xdp_firewall(ctx) { 33 | Ok(ret) => ret, 34 | Err(_) => xdp_action::XDP_ABORTED, 35 | } 36 | } 37 | 38 | #[inline(always)] 39 | unsafe fn ptr_at(ctx: &XdpContext, offset: usize) -> Result<*const T, ()> { 40 | let start = ctx.data(); 41 | let end = ctx.data_end(); 42 | let len = mem::size_of::(); 43 | 44 | if start + offset + len > end { 45 | return Err(()); 46 | } 47 | 48 | Ok((start + offset) as *const T) 49 | } 50 | 51 | fn block_ip(address: u32) -> bool { 52 | unsafe { BLOCKLIST.get(&address).is_some() } 53 | } 54 | 55 | fn try_xdp_firewall(ctx: XdpContext) -> Result { 56 | let h_proto = u16::from_be(unsafe { *ptr_at(&ctx, offset_of!(ethhdr, h_proto))? }); 57 | if h_proto != ETH_P_IP { 58 | return Ok(xdp_action::XDP_PASS); 59 | } 60 | let source = u32::from_be(unsafe { *ptr_at(&ctx, ETH_HDR_LEN + offset_of!(iphdr, saddr))? }); 61 | 62 | let action = if block_ip(source) { 63 | xdp_action::XDP_DROP 64 | } else { 65 | xdp_action::XDP_PASS 66 | }; 67 | 68 | let log_entry = PacketLog { 69 | ipv4_address: source, 70 | action: action, 71 | }; 72 | 73 | unsafe { 74 | EVENTS.output(&ctx, &log_entry, 0); 75 | } 76 | 77 | Ok(action) 78 | } 79 | 80 | const ETH_P_IP: u16 = 0x0800; 81 | const ETH_HDR_LEN: usize = mem::size_of::(); -------------------------------------------------------------------------------- /src/files/InjectConstructed.json: -------------------------------------------------------------------------------- 1 | { 2 | "ethernetLayer" : { 3 | "SrcMAC" : "FF-AA-FA-AA-FF-AA", 4 | "DstMAC" : "BD-BD-BD-BD-BD-BD" 5 | }, 6 | "ipLayer" : { 7 | "SrcIP" : "127.0.0.1", 8 | "DstIP" : "8.8.8.8" 9 | }, 10 | "tcpLayer" : { 11 | "SrcPort" : 4321, 12 | "DstPort" : 80 13 | }, 14 | "payload" : "Hello World" 15 | } -------------------------------------------------------------------------------- /src/files/InjectRaw.txt: -------------------------------------------------------------------------------- 1 | Hello 2 | -------------------------------------------------------------------------------- /src/files/firewall.txt: -------------------------------------------------------------------------------- 1 | 94.182.130.10 -------------------------------------------------------------------------------- /src/web/controllers/auth/auth.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import "github.com/gofiber/fiber/v2" 4 | 5 | func Login(c *fiber.Ctx) error { 6 | return c.SendString("Server is running! Send your request") 7 | } 8 | -------------------------------------------------------------------------------- /src/web/controllers/base.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import "github.com/gofiber/fiber/v2" 4 | 5 | func Status(c *fiber.Ctx) error { 6 | return c.SendString("Server is running! Send your request") 7 | } 8 | -------------------------------------------------------------------------------- /src/web/go.mod: -------------------------------------------------------------------------------- 1 | module web 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/andybalholm/brotli v1.0.4 // indirect 7 | github.com/dropbox/goebpf v0.0.0-20220129191406-26833cbb7e4d 8 | github.com/fasthttp/websocket v1.5.0 // indirect 9 | github.com/gofiber/fiber/v2 v2.32.0 10 | github.com/gofiber/websocket/v2 v2.0.21 11 | github.com/google/gopacket v1.1.19 12 | github.com/klauspost/compress v1.15.1 // indirect 13 | github.com/savsgio/gotils v0.0.0-20220401102855-e56b59f40436 // indirect 14 | github.com/valyala/fasthttp v1.35.0 // indirect 15 | github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect 16 | golang.org/x/net v0.0.0-20220421235706-1d1ef9303861 // indirect 17 | golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect 18 | ) 19 | 20 | require ( 21 | github.com/valyala/bytebufferpool v1.0.0 // indirect 22 | github.com/valyala/tcplisten v1.0.0 // indirect 23 | github.com/vishvananda/netlink v1.2.0-beta // indirect 24 | ) 25 | -------------------------------------------------------------------------------- /src/web/init/init.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | import ( 4 | routes "packiffer/src/web/routes" 5 | 6 | "github.com/gofiber/fiber/v2" 7 | ) 8 | 9 | func run() { 10 | app := fiber.New() 11 | routes.Setup(app) 12 | app.Listen(":3000") 13 | } 14 | -------------------------------------------------------------------------------- /src/web/models/auth/login_model.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | type Login struct { 4 | Username string `json:"username" validate:"required,lte=255"` 5 | Password string `json:"password" validate:"required,lte=255"` 6 | } 7 | -------------------------------------------------------------------------------- /src/web/models/base.go: -------------------------------------------------------------------------------- 1 | package models 2 | -------------------------------------------------------------------------------- /src/web/routes/auth/auth.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | auth_controller "packiffer/src/web/controllers/auth" 5 | 6 | "github.com/gofiber/fiber/v2" 7 | ) 8 | 9 | func Setup(app *fiber.App) { 10 | app.Post("/auth/login", auth_controller.Login) 11 | } 12 | -------------------------------------------------------------------------------- /src/web/routes/base.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | auth_routes "packiffer/src/web/routes/auth" 5 | 6 | "github.com/gofiber/fiber/v2" 7 | 8 | base_controller "packiffer/src/web/controllers" 9 | ) 10 | 11 | func Setup(app *fiber.App) { 12 | app.Get("/", base_controller.Status) 13 | auth_routes.Setup(app) 14 | } 15 | --------------------------------------------------------------------------------