ipset: 1. ipset flush; 2. ipset in main config

This commit is contained in:
nadoo 2017-08-29 18:36:42 +08:00
parent 45a03ff62d
commit e7dd21289f
5 changed files with 85 additions and 26 deletions

View File

@ -38,6 +38,7 @@ TODO:
- [ ] TUN/TAP device support - [ ] TUN/TAP device support
- [ ] Code refactoring: support proxy registering so it can be pluggable - [ ] Code refactoring: support proxy registering so it can be pluggable
- [ ] Conditional compilation so we can abandon needless proxy type and get a smaller binary size - [ ] Conditional compilation so we can abandon needless proxy type and get a smaller binary size
- [ ] IPv6 support
- [ ] SSH tunnel support - [ ] SSH tunnel support
## Install ## Install

View File

@ -42,7 +42,7 @@ func confInit() {
flag.StringVar(&conf.DNS, "dns", "", "dns listen address") flag.StringVar(&conf.DNS, "dns", "", "dns listen address")
flag.StringSliceUniqVar(&conf.DNSServer, "dnsserver", []string{"8.8.8.8:53"}, "remote dns server") flag.StringSliceUniqVar(&conf.DNSServer, "dnsserver", []string{"8.8.8.8:53"}, "remote dns server")
flag.StringVar(&conf.IPSet, "ipset", "glider", "ipset name") flag.StringVar(&conf.IPSet, "ipset", "", "ipset name")
flag.Usage = usage flag.Usage = usage
err := flag.Parse() err := flag.Parse()

View File

@ -27,6 +27,7 @@ const IPSET_MAXNAMELEN = 32
/* Message types and commands */ /* Message types and commands */
const IPSET_CMD_CREATE = 2 const IPSET_CMD_CREATE = 2
const IPSET_CMD_FLUSH = 4
const IPSET_CMD_ADD = 9 const IPSET_CMD_ADD = 9
const IPSET_CMD_DEL = 10 const IPSET_CMD_DEL = 10
@ -38,7 +39,9 @@ const IPSET_ATTR_REVISION = 4 /* 4: Settype revision */
const IPSET_ATTR_FAMILY = 5 /* 5: Settype family */ const IPSET_ATTR_FAMILY = 5 /* 5: Settype family */
const IPSET_ATTR_DATA = 7 /* 7: Nested attributes */ const IPSET_ATTR_DATA = 7 /* 7: Nested attributes */
/* CADT specific attributes */
const IPSET_ATTR_IP = 1 const IPSET_ATTR_IP = 1
const IPSET_ATTR_CIDR = 3
/* IP specific attributes */ /* IP specific attributes */
const IPSET_ATTR_IPADDR_IPV4 = 1 const IPSET_ATTR_IPADDR_IPV4 = 1
@ -54,10 +57,11 @@ type IPSetManager struct {
fd int fd int
lsa syscall.SockaddrNetlink lsa syscall.SockaddrNetlink
mainSet string
domainSet sync.Map domainSet sync.Map
} }
func NewIPSetManager(rules []*RuleConf) (*IPSetManager, error) { func NewIPSetManager(mainSet string, rules []*RuleConf) (*IPSetManager, error) {
fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_NETFILTER) fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_NETFILTER)
if err != nil { if err != nil {
logf("%s", err) logf("%s", err)
@ -74,32 +78,37 @@ func NewIPSetManager(rules []*RuleConf) (*IPSetManager, error) {
return nil, err return nil, err
} }
var domainSet sync.Map m := &IPSetManager{fd: fd, lsa: lsa, mainSet: mainSet}
CreateSet(fd, lsa, mainSet)
for _, r := range rules { for _, r := range rules {
if r.IPSet == "" { set := r.IPSet
continue
if set != "" && set != m.mainSet {
CreateSet(fd, lsa, set)
} else {
set = m.mainSet
} }
CreateSet(fd, lsa, r.IPSet)
for _, domain := range r.Domain { for _, domain := range r.Domain {
domainSet.Store(domain, r.IPSet) m.domainSet.Store(domain, set)
} }
for _, ip := range r.IP { for _, ip := range r.IP {
AddToSet(fd, lsa, mainSet, ip)
AddToSet(fd, lsa, r.IPSet, ip) AddToSet(fd, lsa, r.IPSet, ip)
} }
// TODO: add all ip in cidr to ipset for _, cidr := range r.CIDR {
// for _, s := range r.CIDR { AddToSet(fd, lsa, mainSet, cidr)
// if _, cidr, err := net.ParseCIDR(s); err == nil { AddToSet(fd, lsa, r.IPSet, cidr)
// rd.cidrMap.Store(cidr, sd)
// }
// }
} }
return &IPSetManager{fd: fd, lsa: lsa, domainSet: domainSet}, nil }
return m, nil
} }
// AddDomainIP used to update ipset according to domainSet rule // AddDomainIP used to update ipset according to domainSet rule
@ -113,8 +122,8 @@ func (m *IPSetManager) AddDomainIP(domain, ip string) error {
// find in domainMap // find in domainMap
if ipset, ok := m.domainSet.Load(domain); ok { if ipset, ok := m.domainSet.Load(domain); ok {
AddToSet(m.fd, m.lsa, m.mainSet, ip)
AddToSet(m.fd, m.lsa, ipset.(string), ip) AddToSet(m.fd, m.lsa, ipset.(string), ip)
logf("ipset: domain: %s, ip: %s\n", domain, ip)
} }
} }
@ -123,11 +132,16 @@ func (m *IPSetManager) AddDomainIP(domain, ip string) error {
} }
func CreateSet(fd int, lsa syscall.SockaddrNetlink, setName string) { func CreateSet(fd int, lsa syscall.SockaddrNetlink, setName string) {
if setName == "" {
return
}
if len(setName) > IPSET_MAXNAMELEN { if len(setName) > IPSET_MAXNAMELEN {
log.Fatal("ipset name too long") log.Fatal("ipset name too long")
} }
// req := NewNetlinkRequest(1538, syscall.NLM_F_REQUEST) logf("ipset: create %s hash:net", setName)
req := NewNetlinkRequest(IPSET_CMD_CREATE|(NFNL_SUBSYS_IPSET<<8), syscall.NLM_F_REQUEST) req := NewNetlinkRequest(IPSET_CMD_CREATE|(NFNL_SUBSYS_IPSET<<8), syscall.NLM_F_REQUEST)
// TODO: support AF_INET6 // TODO: support AF_INET6
@ -140,7 +154,7 @@ func CreateSet(fd int, lsa syscall.SockaddrNetlink, setName string) {
attrSiteName := NewRtAttr(IPSET_ATTR_SETNAME, ZeroTerminated(setName)) attrSiteName := NewRtAttr(IPSET_ATTR_SETNAME, ZeroTerminated(setName))
req.AddData(attrSiteName) req.AddData(attrSiteName)
attrSiteType := NewRtAttr(IPSET_ATTR_TYPENAME, ZeroTerminated("hash:ip")) attrSiteType := NewRtAttr(IPSET_ATTR_TYPENAME, ZeroTerminated("hash:net"))
req.AddData(attrSiteType) req.AddData(attrSiteType)
attrRev := NewRtAttr(IPSET_ATTR_REVISION, Uint8Attr(1)) attrRev := NewRtAttr(IPSET_ATTR_REVISION, Uint8Attr(1))
@ -157,14 +171,49 @@ func CreateSet(fd int, lsa syscall.SockaddrNetlink, setName string) {
logf("%s", err) logf("%s", err)
} }
FlushSet(fd, lsa, setName)
}
func FlushSet(fd int, lsa syscall.SockaddrNetlink, setName string) {
logf("ipset: flush %s", setName)
req := NewNetlinkRequest(IPSET_CMD_FLUSH|(NFNL_SUBSYS_IPSET<<8), syscall.NLM_F_REQUEST)
// TODO: support AF_INET6
req.AddData(NewNfGenMsg(syscall.AF_INET, 0, 0))
req.AddData(NewRtAttr(IPSET_ATTR_PROTOCOL, Uint8Attr(IPSET_PROTOCOL)))
req.AddData(NewRtAttr(IPSET_ATTR_SETNAME, ZeroTerminated(setName)))
err := syscall.Sendto(fd, req.Serialize(), 0, &lsa)
if err != nil {
logf("%s", err)
}
}
func AddToSet(fd int, lsa syscall.SockaddrNetlink, setName, entry string) {
if setName == "" {
return
} }
func AddToSet(fd int, lsa syscall.SockaddrNetlink, setName, ipStr string) {
if len(setName) > IPSET_MAXNAMELEN { if len(setName) > IPSET_MAXNAMELEN {
logf("ipset name too long") logf("ipset name too long")
} }
ip := net.ParseIP(ipStr).To4() logf("ipset: add %s %s", setName, entry)
var ip net.IP
var cidr *net.IPNet
ip, cidr, err := net.ParseCIDR(entry)
if err != nil {
ip = net.ParseIP(entry)
}
if ip == nil {
logf("ipset: parse %s error", entry)
return
}
req := NewNetlinkRequest(IPSET_CMD_ADD|(NFNL_SUBSYS_IPSET<<8), syscall.NLM_F_REQUEST) req := NewNetlinkRequest(IPSET_CMD_ADD|(NFNL_SUBSYS_IPSET<<8), syscall.NLM_F_REQUEST)
@ -180,11 +229,20 @@ func AddToSet(fd int, lsa syscall.SockaddrNetlink, setName, ipStr string) {
attrNested := NewRtAttr(IPSET_ATTR_DATA|NLA_F_NESTED, nil) attrNested := NewRtAttr(IPSET_ATTR_DATA|NLA_F_NESTED, nil)
attrIP := NewRtAttrChild(attrNested, IPSET_ATTR_IP|NLA_F_NESTED, nil) attrIP := NewRtAttrChild(attrNested, IPSET_ATTR_IP|NLA_F_NESTED, nil)
NewRtAttrChild(attrIP, IPSET_ATTR_IPADDR_IPV4|NLA_F_NET_BYTEORDER, ip)
// NewRtAttrChild(attrNested, 9|NLA_F_NET_BYTEORDER, Uint32Attr(0)) // TODO: support ipV6
NewRtAttrChild(attrIP, IPSET_ATTR_IPADDR_IPV4|NLA_F_NET_BYTEORDER, ip.To4())
// for cidr prefix
if cidr != nil {
cidrPrefix, _ := cidr.Mask.Size()
NewRtAttrChild(attrNested, IPSET_ATTR_CIDR, Uint8Attr(uint8(cidrPrefix)))
}
NewRtAttrChild(attrNested, 9|NLA_F_NET_BYTEORDER, Uint32Attr(0))
req.AddData(attrNested) req.AddData(attrNested)
err := syscall.Sendto(fd, req.Serialize(), 0, &lsa) err = syscall.Sendto(fd, req.Serialize(), 0, &lsa)
if err != nil { if err != nil {
logf("%s", err) logf("%s", err)
} }

View File

@ -7,7 +7,7 @@ import "errors"
type IPSetManager struct { type IPSetManager struct {
} }
func NewIPSetManager(rules []*RuleConf) (*IPSetManager, error) { func NewIPSetManager(mainSet string, rules []*RuleConf) (*IPSetManager, error) {
return nil, errors.New("ipset not supported on this os") return nil, errors.New("ipset not supported on this os")
} }

View File

@ -43,9 +43,9 @@ func main() {
go local.ListenAndServe() go local.ListenAndServe()
} }
ipsetM, err := NewIPSetManager(conf.rules) ipsetM, err := NewIPSetManager(conf.IPSet, conf.rules)
if err != nil { if err != nil {
logf("ipset error: %s", err) logf("create ipset manager error: %s", err)
} }
if conf.DNS != "" { if conf.DNS != "" {