2022-11-10 15:06:24 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"log"
|
|
|
|
"net"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/google/gopacket"
|
|
|
|
layers "github.com/google/gopacket/layers"
|
|
|
|
"github.com/google/gopacket/pcapgo"
|
|
|
|
"srs.epita.fr/fic-server/admin/sync"
|
|
|
|
fic "srs.epita.fr/fic-server/libfic"
|
|
|
|
)
|
|
|
|
|
|
|
|
// This interface abstract pcap and pcapng data acquisition
|
|
|
|
// pcapgo.Reader and pcapgo.NgReader both use signature :
|
|
|
|
// ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error)
|
|
|
|
type PcapPacketDataReader interface {
|
|
|
|
ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wrap pcago.Reader as we can't impl its interface outside its package
|
|
|
|
type PcapReader struct {
|
|
|
|
*pcapgo.Reader
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wrap pcago.NgReader as we can't impl its interface outside its package
|
|
|
|
type PcapNgReader struct {
|
|
|
|
*pcapgo.NgReader
|
|
|
|
}
|
|
|
|
|
|
|
|
// Impl interface for reading pcap and pcapng data
|
|
|
|
func (pcapReader *PcapReader) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) {
|
|
|
|
return pcapReader.Reader.ReadPacketData()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (pcapNGReader *PcapNgReader) ReadPacketData() (data []byte, ci gopacket.CaptureInfo, err error) {
|
|
|
|
return pcapNGReader.NgReader.ReadPacketData()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Iterate thought each packet to find potentialy unwanted packets
|
|
|
|
// TODO: Allow custom rules to specify what is a unwanted packet
|
2023-11-22 11:16:53 +00:00
|
|
|
func CheckPcap(pcapReader PcapPacketDataReader, pcapName string) (errs error) {
|
2022-11-10 15:06:24 +00:00
|
|
|
warningFlows := make(map[gopacket.Flow]([]time.Time))
|
|
|
|
|
|
|
|
//
|
|
|
|
// Handle packets from network layer section
|
|
|
|
//
|
|
|
|
data, ci, err := pcapReader.ReadPacketData()
|
|
|
|
for ; err == nil; data, ci, err = pcapReader.ReadPacketData() {
|
|
|
|
|
|
|
|
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.Default)
|
|
|
|
packetNetworkLayer := packet.NetworkLayer()
|
|
|
|
|
|
|
|
// No network layer
|
|
|
|
if packetNetworkLayer == nil {
|
|
|
|
continue
|
|
|
|
}
|
2022-11-10 15:14:02 +00:00
|
|
|
|
2022-11-10 15:06:24 +00:00
|
|
|
flow := packetNetworkLayer.NetworkFlow()
|
|
|
|
|
|
|
|
ENDPOINT_SELECTION:
|
|
|
|
switch flow.EndpointType() {
|
|
|
|
|
|
|
|
case layers.EndpointIPv4, layers.EndpointIPv6:
|
|
|
|
src, dst := flow.Endpoints()
|
|
|
|
|
|
|
|
if net.ParseIP(src.String()).IsPrivate() &&
|
|
|
|
net.ParseIP(dst.String()).IsPrivate() {
|
|
|
|
|
|
|
|
warningFlows[flow] = append(warningFlows[flow], ci.Timestamp)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Really ?
|
|
|
|
default:
|
|
|
|
break ENDPOINT_SELECTION
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if os.Getenv("VERBOSE_PCAP_CHECK") != "" {
|
|
|
|
for flow, timestamps := range warningFlows {
|
|
|
|
log.Printf(
|
|
|
|
"(%s) Found communication between two private IPs (%s => %s) at timestamps:",
|
|
|
|
pcapName,
|
|
|
|
flow.Src().String(),
|
|
|
|
flow.Dst().String())
|
|
|
|
|
|
|
|
for _, timestamp := range timestamps {
|
|
|
|
log.Printf("\t%s", timestamp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(warningFlows) > 0 {
|
|
|
|
log.Printf("/!\\ %s: Found %d endpoints communicating with private IPs \n => Set VERBOSE_PCAP_CHECK env variable for details",
|
|
|
|
pcapName,
|
|
|
|
len(warningFlows))
|
|
|
|
} else {
|
|
|
|
log.Printf("%s: No endpoints communicating with private IPs \n",
|
|
|
|
pcapName)
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-11-22 11:16:53 +00:00
|
|
|
func CheckTextFile(fd *os.File) (errs error) {
|
2022-11-10 15:06:24 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-11-22 11:16:53 +00:00
|
|
|
func InspectFileForIPAddr(file *fic.EFile, _ *fic.Exercice, exceptions *sync.CheckExceptions) (errs error) {
|
2022-11-21 18:02:37 +00:00
|
|
|
fd, closer, err := sync.GetFile(sync.GlobalImporter, file.GetOrigin())
|
2022-11-10 15:06:24 +00:00
|
|
|
if err != nil {
|
2022-11-21 18:02:37 +00:00
|
|
|
log.Printf("Unable to open %q: %s", file.GetOrigin(), err.Error())
|
2022-11-10 15:06:24 +00:00
|
|
|
return
|
|
|
|
}
|
2022-11-21 18:02:37 +00:00
|
|
|
defer closer()
|
2022-11-10 15:06:24 +00:00
|
|
|
|
|
|
|
switch filepath.Ext(file.Name) {
|
|
|
|
case ".pcap":
|
|
|
|
pcapReader, err := pcapgo.NewReader(fd)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("Unable to load the pcap file, please check if it is a real pcap file")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
errs = CheckPcap(&PcapReader{pcapReader}, file.Name)
|
|
|
|
|
|
|
|
case ".pcapng":
|
|
|
|
pcapNgReader, err := pcapgo.NewNgReader(fd, pcapgo.DefaultNgReaderOptions)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("Unable to load the pcapng file, please check if it is a real pcapng file")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
errs = CheckPcap(&PcapNgReader{pcapNgReader}, file.Name)
|
|
|
|
|
|
|
|
default:
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|