Browse Source

blocking by tables

master
Vladimir Smagin 1 month ago
parent
commit
792b4dc995
9 changed files with 277 additions and 20 deletions
  1. +1
    -0
      go.mod
  2. +2
    -0
      go.sum
  3. +13
    -0
      ip-blocker-set.sh
  4. BIN
      ips.sdb
  5. +30
    -20
      main.go
  6. +20
    -0
      vendor/honnef.co/go/netdb/LICENSE
  7. +12
    -0
      vendor/honnef.co/go/netdb/README.md
  8. +196
    -0
      vendor/honnef.co/go/netdb/netdb.go
  9. +3
    -0
      vendor/modules.txt

+ 1
- 0
go.mod View File

@@ -6,4 +6,5 @@ require (
github.com/gorilla/mux v1.7.4
github.com/mattn/go-sqlite3 v2.0.3+incompatible
gopkg.in/yaml.v2 v2.3.0
honnef.co/go/netdb v0.0.0-20150201073656-a416d700ae39
)

+ 2
- 0
go.sum View File

@@ -7,3 +7,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/netdb v0.0.0-20150201073656-a416d700ae39 h1:Oyv66NRkI9fnsvTlaB9foJojt8Lt34vcX8SMNqsvw6U=
honnef.co/go/netdb v0.0.0-20150201073656-a416d700ae39/go.mod h1:rbNo0ST5hSazCG4rGfpHrwnwvzP1QX62WbhzD+ghGzs=

+ 13
- 0
ip-blocker-set.sh View File

@@ -0,0 +1,13 @@
#!/bin/bash

# cron for every minute run

source /etc/profile
IFS=$'\n'
IPs=$(curl -s http://my-watchtower.ru:34534/list/1)

for ip in $IPs
do
echo "Blocking IP $ip"
fail2ban-client set sshd banip $ip
done

BIN
ips.sdb View File


+ 30
- 20
main.go View File

@@ -14,6 +14,7 @@ import (
"github.com/gorilla/mux"
_ "github.com/mattn/go-sqlite3"
"gopkg.in/yaml.v2"
"honnef.co/go/netdb"
)

const (
@@ -41,12 +42,13 @@ type AppConfig struct {
}

type IP struct {
ID string
Updated string
Origin string
Protocol string
Port int
IP string
ID string
Updated string
Origin string
Protocol string
Port int
IP string
BlockTable string
}

var (
@@ -79,7 +81,7 @@ func (d *BlockIPdb) dbInit() error {
if err != nil {
if err == sql.ErrNoRows {
log.Println("Initializing database")
createTable := "create table ip (id integer not null primary key, origin text, updated int, protocol text, port int, ip text unique);"
createTable := "create table ip (id integer not null primary key, origin text, updated int, protocol text, port int, ip text unique, blocktable text);"
_, err = d.HandlerDB.Exec(createTable)
if err != nil {
return err
@@ -166,8 +168,8 @@ func main() {

r := mux.NewRouter()
r.HandleFunc("/", HandlerHealth)
r.HandleFunc("/set/{origin}/{ip}/{proto}/{port}", HandlerSet)
r.HandleFunc("/list/{minutes}", HandlerList)
r.HandleFunc("/set/{origin}/{blocktable}/{ip}/{proto}/{port}", HandlerSet)
r.HandleFunc("/list/{blocktable}/{minutes}", HandlerList)
// http.Handle("/", r)
srv := &http.Server{
Handler: r,
@@ -185,6 +187,7 @@ func HandlerHealth(w http.ResponseWriter, r *http.Request) {

func HandlerList(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
blockTable := vars["blocktable"]
minutes, err := strconv.Atoi(vars["minutes"])
if err != nil {
log.Println(err)
@@ -194,9 +197,9 @@ func HandlerList(w http.ResponseWriter, r *http.Request) {

rows := &sql.Rows{}
if minutes != 0 {
rows, err = blockIP.HandlerDB.Query("select ip from ip WHERE updated >= (strftime('%s','now') - (60 * ?));", minutes)
rows, err = blockIP.HandlerDB.Query("select ip from ip WHERE blocktable=? and updated >= (strftime('%s','now') - (60 * ?));", blockTable, minutes)
} else {
rows, err = blockIP.HandlerDB.Query("select ip from ip")
rows, err = blockIP.HandlerDB.Query("select ip from ip where blocktable=?", blockTable)
}
defer rows.Close()
w.WriteHeader(http.StatusOK)
@@ -216,36 +219,43 @@ func HandlerList(w http.ResponseWriter, r *http.Request) {

func HandlerSet(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
log.Println("Got set request", vars)

ip := IP{
Origin: vars["origin"],
IP: vars["ip"],
Protocol: vars["proto"],
IP: vars["ip"],
Protocol: vars["proto"],
BlockTable: vars["blocktable"],
}

port, err := strconv.Atoi(vars["port"])
if err != nil {
log.Println(err)
return
serv := netdb.GetServByName(vars["port"], netdb.GetProtoByName(ip.Protocol))
if serv != nil {
ip.Port = serv.Port
} else {
log.Println(err)
return
}
} else {
ip.Port = port
}
ip.Port = port

// query ip before insert
var count int
err = blockIP.HandlerDB.QueryRow("select count(ip) from ip WHERE ip=?;", ip.IP).Scan(&count)
err = blockIP.HandlerDB.QueryRow("select count(ip) from ip WHERE blocktable=? and ip=?;", ip.BlockTable, ip.IP).Scan(&count)
if err != nil {
log.Println(err)
}

if count > 0 {
log.Println("Update IP timestamp:", ip.IP)
_, err := blockIP.HandlerDB.Exec("update ip set updated=strftime('%s','now') where ip='?'", ip.IP)
_, err := blockIP.HandlerDB.Exec("update ip set updated=strftime('%s','now') where blocktable=? and ip='?'", ip.BlockTable, ip.IP)
if err != nil {
log.Println(err)
}
} else {
log.Println("New IP:", ip.IP)
_, err := blockIP.HandlerDB.Exec("insert into ip(origin, ip, protocol, port, updated) values(?, ?, ?, ?, strftime('%s','now'))", ip.Origin, ip.IP, ip.Protocol, ip.Port)
_, err := blockIP.HandlerDB.Exec("insert into ip(origin, ip, protocol, port, updated, blocktable) values(?, ?, ?, ?, strftime('%s','now'), ?)", ip.Origin, ip.IP, ip.Protocol, ip.Port, ip.BlockTable)
if err != nil {
log.Println(err)
}


+ 20
- 0
vendor/honnef.co/go/netdb/LICENSE View File

@@ -0,0 +1,20 @@
Copyright (c) 2012 Dominik Honnef

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 12
- 0
vendor/honnef.co/go/netdb/README.md View File

@@ -0,0 +1,12 @@
# netdb

## Install

```sh
go get honnef.co/go/netdb
```

## Documentation

Documentation can be found at
[godoc.org](http://godoc.org/honnef.co/go/netdb).

+ 196
- 0
vendor/honnef.co/go/netdb/netdb.go View File

@@ -0,0 +1,196 @@
// Package netdb provides a Go interface for the protoent and servent
// structures as defined in netdb.h
//
// A pure Go implementation is used by parsing /etc/protocols and
// /etc/services
//
// All return values are pointers that point to the entries in the
// original list of protocols and services. Manipulating the entries
// would affect the entire program.
package netdb // import "honnef.co/go/netdb"

import (
"io/ioutil"
"strconv"
"strings"
)

type Protoent struct {
Name string
Aliases []string
Number int
}

type Servent struct {
Name string
Aliases []string
Port int
Protocol *Protoent
}

// These variables get populated from /etc/protocols and /etc/services
// respectively.
var (
Protocols []*Protoent
Services []*Servent
)

func init() {
protoMap := make(map[string]*Protoent)

// Load protocols
data, err := ioutil.ReadFile("/etc/protocols")
if err != nil {
panic(err)
}

for _, line := range strings.Split(string(data), "\n") {
line = strings.TrimSpace(line)
split := strings.SplitN(line, "#", 2)
fields := strings.Fields(split[0])
if len(fields) < 2 {
continue
}

num, err := strconv.ParseInt(fields[1], 10, 32)
if err != nil {
panic(err)
}

protoent := &Protoent{
Name: fields[0],
Aliases: fields[2:],
Number: int(num),
}
Protocols = append(Protocols, protoent)

protoMap[fields[0]] = protoent
}

// Load services
data, err = ioutil.ReadFile("/etc/services")
if err != nil {
panic(err)
}

for _, line := range strings.Split(string(data), "\n") {
line = strings.TrimSpace(line)
split := strings.SplitN(line, "#", 2)
fields := strings.Fields(split[0])
if len(fields) < 2 {
continue
}

name := fields[0]
portproto := strings.SplitN(fields[1], "/", 2)
port, err := strconv.ParseInt(portproto[0], 10, 32)
if err != nil {
panic(err)
}

proto := portproto[1]
aliases := fields[2:]

Services = append(Services, &Servent{
Name: name,
Aliases: aliases,
Port: int(port),
Protocol: protoMap[proto],
})
}
}

// Equal checks if two Protoents are the same, which is the case if
// their protocol numbers are identical or when both Protoents are
// nil.
func (this *Protoent) Equal(other *Protoent) bool {
if this == nil && other == nil {
return true
}

if this == nil || other == nil {
return false
}

return this.Number == other.Number
}

// Equal checks if two Servents are the same, which is the case if
// their port numbers and protocols are identical or when both
// Servents are nil.
func (this *Servent) Equal(other *Servent) bool {
if this == nil && other == nil {
return true
}

if this == nil || other == nil {
return false
}

return this.Port == other.Port &&
this.Protocol.Equal(other.Protocol)
}

// GetProtoByNumber returns the Protoent for a given protocol number.
func GetProtoByNumber(num int) (protoent *Protoent) {
for _, protoent := range Protocols {
if protoent.Number == num {
return protoent
}
}
return nil
}

// GetProtoByName returns the Protoent whose name or any of its
// aliases matches the argument.
func GetProtoByName(name string) (protoent *Protoent) {
for _, protoent := range Protocols {
if protoent.Name == name {
return protoent
}

for _, alias := range protoent.Aliases {
if alias == name {
return protoent
}
}
}

return nil
}

// GetServByName returns the Servent for a given service name or alias
// and protocol. If the protocol is nil, the first service matching
// the service name is returned.
func GetServByName(name string, protocol *Protoent) (servent *Servent) {
for _, servent := range Services {
if !servent.Protocol.Equal(protocol) {
continue
}

if servent.Name == name {
return servent
}

for _, alias := range servent.Aliases {
if alias == name {
return servent
}
}
}

return nil
}

// GetServByPort returns the Servent for a given port number and
// protocol. If the protocol is nil, the first service matching the
// port number is returned.
func GetServByPort(port int, protocol *Protoent) *Servent {
for _, servent := range Services {
if servent.Port == port && servent.Protocol.Equal(protocol) {
return servent
}
}

return nil
}

+ 3
- 0
vendor/modules.txt View File

@@ -7,3 +7,6 @@ github.com/mattn/go-sqlite3
# gopkg.in/yaml.v2 v2.3.0
## explicit
gopkg.in/yaml.v2
# honnef.co/go/netdb v0.0.0-20150201073656-a416d700ae39
## explicit
honnef.co/go/netdb

Loading…
Cancel
Save