├── .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 | [](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 |
--------------------------------------------------------------------------------