potknocker/common/net.go

129 lines
2.1 KiB
Go

package common
import (
"io"
"net"
"net/http"
"strings"
)
var rfc1918 = []string{
"0.0.0.0/8",
"10.0.0.0/8",
"192.168.0.0/16",
"172.16.0.0/12",
}
var excludes []*net.IPNet
func pullbogons() ([]string, error) {
res, err := http.Get("https://www.team-cymru.org/Services/Bogons/fullbogons-ipv4.txt")
if err != nil {
return nil, err
}
if res.StatusCode == 404 {
return nil, err
}
defer res.Body.Close()
b := new(strings.Builder)
_, _ = io.Copy(b, res.Body)
raw := b.String()
parts := strings.Split(raw, "\n")
var bogons []string
for _, r := range parts {
if strings.Contains(r, "#") || !strings.Contains(r, "/") {
continue
}
bogons = append(bogons, r)
}
return bogons, nil
}
func parseranges(ranges []string) error {
for _, r := range ranges {
_, ipnet, err := net.ParseCIDR(r)
if err != nil {
return err
}
excludes = append(excludes, ipnet)
}
return nil
}
func validcidr(cidr string) bool {
_, _, err := net.ParseCIDR(cidr)
if err != nil {
return false
}
return true
}
func broadcast(ipnet *net.IPNet) net.IP {
ip := ipnet.IP.To4()
mask := ipnet.Mask
for i := range ip {
ip[i] |= ^mask[i]
}
return ip
}
func issmaller(submask, supermask net.IPMask) bool {
for i := range submask {
if submask[i] < supermask[i] {
return false
}
}
return true
}
func issubnet(subnet, supernet *net.IPNet) bool {
if !supernet.Contains(subnet.IP) {
return false
}
if !issmaller(subnet.Mask, supernet.Mask) {
return false
}
bc := broadcast(subnet)
return supernet.Contains(bc)
}
func ipexcluded(ip string) bool {
ip_ := net.ParseIP(ip)
for _, ex := range excludes {
if ex.Contains(ip_) {
return true
}
}
return false
}
func cidrexcluded(cidr string) bool {
_, argnet, _ := net.ParseCIDR(cidr)
for _, ex := range excludes {
if issubnet(argnet, ex) {
return true
}
}
return false
}
func SetExcludes() {
if bogons, err := pullbogons(); err == nil && len(bogons) > 4 {
if err = parseranges(bogons); err == nil {
return
}
}
info("error parsing bogon ranges, using rfc1918 defaults")
_ = parseranges(rfc1918)
}