mirror of
https://github.com/bolucat/Archive.git
synced 2025-09-26 20:21:35 +08:00
250 lines
5.2 KiB
Go
250 lines
5.2 KiB
Go
// Copyright (c) 2016-present Cloud <cloud@txthinking.com>
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of version 3 of the GNU General Public
|
|
// License as published by the Free Software Foundation.
|
|
//
|
|
// This program is distributed in the hope that it will be useful, but
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
package brook
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
cache "github.com/patrickmn/go-cache"
|
|
"github.com/phuslu/iploc"
|
|
)
|
|
|
|
func ListHasDomain(ds map[string]byte, domain string, c *cache.Cache) bool {
|
|
if ds == nil {
|
|
return false
|
|
}
|
|
if c != nil {
|
|
any, ok := c.Get(domain)
|
|
if ok {
|
|
return any.(bool)
|
|
}
|
|
}
|
|
ss := strings.Split(domain, ".")
|
|
var s1 string
|
|
for i := len(ss) - 1; i >= 0; i-- {
|
|
if s1 == "" {
|
|
s1 = ss[i]
|
|
} else {
|
|
s1 = ss[i] + "." + s1
|
|
}
|
|
if _, ok := ds[s1]; ok {
|
|
if c != nil {
|
|
c.Set(domain, true, 24*time.Hour)
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
if c != nil {
|
|
c.Set(domain, false, 24*time.Hour)
|
|
}
|
|
return false
|
|
}
|
|
|
|
func ListHasIP(c4, c6 []*net.IPNet, i net.IP, c *cache.Cache, geo []string) bool {
|
|
if c4 == nil && c6 == nil && len(geo) == 0 {
|
|
return false
|
|
}
|
|
if c != nil {
|
|
any, ok := c.Get(i.String())
|
|
if ok {
|
|
return any.(bool)
|
|
}
|
|
}
|
|
if len(geo) != 0 {
|
|
bs := iploc.Country(i)
|
|
if bs != "" {
|
|
for _, v := range geo {
|
|
if v == bs {
|
|
if c != nil {
|
|
c.Set(i.String(), true, 24*time.Hour)
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if i.To4() != nil {
|
|
if c4 == nil {
|
|
return false
|
|
}
|
|
ii := i.To4()
|
|
for _, v := range c4 {
|
|
if v.Contains(ii) {
|
|
if c != nil {
|
|
c.Set(i.String(), true, 24*time.Hour)
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
if i.To4() == nil {
|
|
if c6 == nil {
|
|
return false
|
|
}
|
|
ii := i.To16()
|
|
for _, v := range c6 {
|
|
if v.Contains(ii) {
|
|
if c != nil {
|
|
c.Set(i.String(), true, 24*time.Hour)
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
if c != nil {
|
|
c.Set(i.String(), false, 24*time.Hour)
|
|
}
|
|
return false
|
|
}
|
|
|
|
func ReadDomainList(url string) (map[string]byte, error) {
|
|
ds := make(map[string]byte)
|
|
ss, err := ReadList(url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, v := range ss {
|
|
ds[v] = 0
|
|
}
|
|
return ds, nil
|
|
}
|
|
|
|
func ReadCIDRList(url string) ([]*net.IPNet, error) {
|
|
c := make([]*net.IPNet, 0)
|
|
l, err := ReadList(url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, v := range l {
|
|
_, in, err := net.ParseCIDR(v)
|
|
if err != nil {
|
|
Log(Error{"when": "net.ParseCIDR", "cidr": v, "error": err.Error()})
|
|
continue
|
|
}
|
|
c = append(c, in)
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
func ReadList(url string) ([]string, error) {
|
|
var data []byte
|
|
var err error
|
|
if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") {
|
|
c := &http.Client{
|
|
Timeout: 9 * time.Second,
|
|
Transport: &http.Transport{
|
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
h, p, err := net.SplitHostPort(addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s, err := Resolve6(h)
|
|
if err == nil {
|
|
c, err := net.Dial(network, net.JoinHostPort(s, p))
|
|
if err == nil {
|
|
return c, nil
|
|
}
|
|
}
|
|
s, err = Resolve4(h)
|
|
if err == nil {
|
|
c, err := net.Dial(network, net.JoinHostPort(s, p))
|
|
if err == nil {
|
|
return c, nil
|
|
}
|
|
}
|
|
return nil, errors.New("Can not fetch " + addr)
|
|
},
|
|
},
|
|
}
|
|
r, err := c.Get(url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer r.Body.Close()
|
|
data, err = io.ReadAll(r.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
|
|
data, err = os.ReadFile(url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
data = bytes.TrimSpace(data)
|
|
data = bytes.Replace(data, []byte{0x20}, []byte{}, -1)
|
|
data = bytes.Replace(data, []byte{0x0d, 0x0a}, []byte{0x0a}, -1)
|
|
ss := strings.Split(string(data), "\n")
|
|
return ss, nil
|
|
}
|
|
|
|
func ReadData(url string) ([]byte, error) {
|
|
var data []byte
|
|
var err error
|
|
if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") {
|
|
c := &http.Client{
|
|
Timeout: 9 * time.Second,
|
|
Transport: &http.Transport{
|
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
|
h, p, err := net.SplitHostPort(addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s, err := Resolve6(h)
|
|
if err == nil {
|
|
c, err := net.Dial(network, net.JoinHostPort(s, p))
|
|
if err == nil {
|
|
return c, nil
|
|
}
|
|
}
|
|
s, err = Resolve4(h)
|
|
if err == nil {
|
|
c, err := net.Dial(network, net.JoinHostPort(s, p))
|
|
if err == nil {
|
|
return c, nil
|
|
}
|
|
}
|
|
return nil, errors.New("Can not fetch " + addr)
|
|
},
|
|
},
|
|
}
|
|
r, err := c.Get(url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer r.Body.Close()
|
|
data, err = io.ReadAll(r.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
|
|
data, err = os.ReadFile(url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return data, nil
|
|
}
|