Skip to content

Commit

Permalink
Merge pull request #7 from asphaltbot/development
Browse files Browse the repository at this point in the history
ability to block ip ranges, fixes #4
  • Loading branch information
cxnky authored Dec 3, 2020
2 parents 871fc54 + c310c09 commit 44980a3
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 8 deletions.
52 changes: 44 additions & 8 deletions blacklist.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,17 @@ package blacklist
import (
"fmt"
"io/ioutil"
"net"
"net/http"
"strings"

"github.com/kataras/iris/v12"
)

// Options is the struct that gets passed in by the user to create the blacklist struct with
// If BlockedResponse is null, we will download and use the created template (see examples/template.html)
// If ReplaceStrings is not null, then {{key}} will be replaced by the corresponding value
// By default, there are a few replace strings which automatically get populated, such as the user's IP address
type Options struct {
BlockedResponse []byte
BlockedIPs []string
BlockedIpRanges []string
BlockedUserAgents []string
ReplaceStrings map[string]string
}
Expand All @@ -24,6 +22,7 @@ type Options struct {
type Blacklist struct {
blockedIPs []string
blockedUserAgents []string
blockedIpRanges []string
blockedResponse []byte
replaceStrings map[string]string
}
Expand All @@ -32,6 +31,7 @@ type Blacklist struct {
func New(options Options) iris.Handler {
b := &Blacklist{
blockedIPs: options.BlockedIPs,
blockedIpRanges: options.BlockedIpRanges,
blockedUserAgents: options.BlockedUserAgents,
blockedResponse: options.BlockedResponse,
replaceStrings: options.ReplaceStrings,
Expand All @@ -43,6 +43,22 @@ func New(options Options) iris.Handler {
b.replaceStrings = defaultReplaceStrings
}

// get the IP addresses within ranges that have been blocked
if b.blockedIpRanges != nil && len(b.blockedIpRanges) != 0 {
for _, v := range b.blockedIpRanges {
ipsInCidr, err := getIpsInCIDR(v)

if err != nil {
fmt.Println("Couldn't get IP addresses in range " + v + ", is it valid?")
continue
}

for _, v := range ipsInCidr {
b.blockedIPs = append(b.blockedIPs, v)
}
}
}

// if the user has not specified a blocked response, then download the template and use that
if b.blockedResponse == nil {
fileBytes, err := b.downloadTemplateFile("https://asphaltbot.com/middleware/blacklist/template.html")
Expand Down Expand Up @@ -94,8 +110,6 @@ func (b *Blacklist) Serve(ctx iris.Context) {

for _, v := range b.blockedUserAgents {
if v == userAgent {
fmt.Println(fmt.Sprintf("the user's user agent has been blocked. showing blocked page"))

ctx.StatusCode(http.StatusForbidden)
ctx.HTML(string(b.returnWithValuesReplaced()))

Expand All @@ -108,8 +122,6 @@ func (b *Blacklist) Serve(ctx iris.Context) {

for _, v := range b.blockedIPs {
if strings.Contains(userIP, v) {
fmt.Println(fmt.Sprintf("the user's IP has been blocked. showing blocked page"))

ctx.StatusCode(http.StatusForbidden)
ctx.HTML(string(b.returnWithValuesReplaced()))

Expand All @@ -122,3 +134,27 @@ func (b *Blacklist) Serve(ctx iris.Context) {
ctx.Next()

}

func getIpsInCIDR(cidr string) ([]string, error) {
ip, ipnet, err := net.ParseCIDR(cidr)
if err != nil {
return nil, err
}

ips := make([]string, 0)
for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
ips = append(ips, ip.String())
}

return ips, nil

}

func inc(ip net.IP) {
for j := len(ip) - 1; j >= 0; j-- {
ip[j]++
if ip[j] > 0 {
break
}
}
}
1 change: 1 addition & 0 deletions example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func main() {
// so you don't need to add that
blacklistMiddleware := blacklist.New(blacklist.Options{
BlockedIPs: []string{"127.0.0.1", "::1"},
BlockedIpRanges: []string{"127.0.0.1/24"},
BlockedUserAgents: []string{},
ReplaceStrings: replaceValues,
})
Expand Down

0 comments on commit 44980a3

Please sign in to comment.