Skip to content

Commit 193a1cf

Browse files
committed
update: SpiderResolver and dns discovery
1 parent 0db99d3 commit 193a1cf

File tree

11 files changed

+255
-91
lines changed

11 files changed

+255
-91
lines changed

cmd/all/all.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ func init() {
2020
}
2121

2222
var AllCmd = &cobra.Command{
23-
Use: "all",
23+
Use: "all",
24+
Aliases: []string{
25+
"a",
26+
},
2427
Short: "all is a tool to discover k8s services and available ip in subnet",
2528
Run: func(cmd *cobra.Command, args []string) {
2629
if command.Opts.Cidr == "" {

cmd/neighbor/neighbor.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ var NeighborCmd = &cobra.Command{
4848
Short: "neighbor is a tool to discover k8s pod and available ip in subnet (require k8s coredns with pod verified config)",
4949
Aliases: []string{"n", "nei"},
5050
Run: func(cmd *cobra.Command, args []string) {
51-
if !pkg.TestPodVerified() {
51+
if !pkg.CheckPodVerified() {
5252
log.Fatalf("k8s coredns with pod verified config could not be set")
5353
}
5454
if Opts.NamespaceWordlist != "" {

cmd/root.go

+6-13
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package cmd
22

33
import (
4-
"context"
54
"fmt"
6-
"net"
75
"os"
86

97
"github.com/esonhugh/k8spider/pkg"
@@ -28,6 +26,7 @@ var Opts = struct {
2826
func init() {
2927
RootCmd.PersistentFlags().StringVarP(&Opts.Cidr, "cidr", "c", os.Getenv("KUBERNETES_SERVICE_HOST")+"/16", "cidr like: 192.168.0.1/16")
3028
RootCmd.PersistentFlags().StringVarP(&Opts.DnsServer, "dns-server", "d", "", "dns server")
29+
RootCmd.PersistentFlags().IntVarP(&pkg.DnsTimeout, "dns-timeout", "i", 2, "dns timeout")
3130
RootCmd.PersistentFlags().StringSliceVarP(&Opts.SvcDomains, "svc-domains", "s", []string{}, "service domains, like: kubernetes.default,etcd.default don't add zone like svc.cluster.local")
3231
RootCmd.PersistentFlags().StringVarP(&Opts.Zone, "zone", "z", "cluster.local", "zone")
3332
RootCmd.PersistentFlags().StringVarP(&Opts.OutputFile, "output-file", "o", "", "output file")
@@ -44,21 +43,15 @@ var RootCmd = &cobra.Command{
4443
Long: "k8spider is a tool to discover k8s services",
4544
PersistentPreRun: func(cmd *cobra.Command, args []string) {
4645
SetLogLevel(Opts.Verbose)
47-
if !Opts.SkipKubeDNSCheck { // Not Skip
48-
if pkg.CheckKubernetes() {
46+
if Opts.DnsServer != "" {
47+
pkg.NetResolver = pkg.WarpDnsServer(Opts.DnsServer)
48+
}
49+
if Opts.SkipKubeDNSCheck == false { // Not Skip
50+
if pkg.CheckKubeDNS() {
4951
log.Warn("current environment is not a kubernetes cluster")
5052
os.Exit(1)
5153
}
5254
}
53-
if Opts.DnsServer != "" {
54-
pkg.NetResolver = &net.Resolver{
55-
PreferGo: true,
56-
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
57-
d := net.Dialer{}
58-
return d.DialContext(ctx, network, Opts.DnsServer)
59-
},
60-
}
61-
}
6255
pkg.Zone = Opts.Zone
6356
},
6457
Run: func(cmd *cobra.Command, args []string) {

cmd/service/service.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ func init() {
1616
}
1717

1818
var ServiceCmd = &cobra.Command{
19-
Use: "service",
19+
Use: "service",
20+
Aliases: []string{
21+
"srv",
22+
},
2023
Short: "service is a tool to discover k8s services",
2124
Run: func(cmd *cobra.Command, args []string) {
2225
if command.Opts.Zone == "" || command.Opts.SvcDomains == nil || len(command.Opts.SvcDomains) == 0 {

cmd/subnet/subnet.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ func init() {
1818
}
1919

2020
var SubNetCmd = &cobra.Command{
21-
Use: "subnet",
21+
Use: "subnet",
22+
Aliases: []string{
23+
"sub",
24+
"s",
25+
},
2226
Short: "subnet is a tool to discover k8s available ip in subnet",
2327
Run: func(cmd *cobra.Command, args []string) {
2428
if command.Opts.Cidr == "" {

cmd/whereisdns/dns.go

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package whereisdns
2+
3+
import (
4+
"fmt"
5+
6+
command "github.com/esonhugh/k8spider/cmd"
7+
"github.com/esonhugh/k8spider/pkg"
8+
log "github.com/sirupsen/logrus"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
func init() {
13+
command.RootCmd.AddCommand(WhereIsDnsCmd)
14+
}
15+
16+
var WhereIsDnsCmd = &cobra.Command{
17+
Use: "whereisdns",
18+
Aliases: []string{
19+
"dns",
20+
},
21+
Short: "this command will help you check where is the dns server in provided CIDR",
22+
Run: func(cmd *cobra.Command, args []string) {
23+
ipNets, err := pkg.ParseStringToIPNet(command.Opts.Cidr)
24+
if err != nil {
25+
log.Warnf("ParseStringToIPNet failed: %v", err)
26+
return
27+
}
28+
s := false
29+
for _, ip := range pkg.ParseIPNetToIPs(ipNets) {
30+
serverAddr := fmt.Sprintf("%s:53", ip.String())
31+
if checkdns(serverAddr) {
32+
s = true
33+
}
34+
serverAddr = fmt.Sprintf("%s:5353", ip.String())
35+
if checkdns(serverAddr) {
36+
s = true
37+
}
38+
}
39+
if s {
40+
log.Warn("DNS Server Not Found!")
41+
}
42+
},
43+
}
44+
45+
func checkdns(serverAddr string) bool {
46+
dns := pkg.WarpDnsServer(serverAddr)
47+
if pkg.CheckKubeDNS(dns) {
48+
log.Infof("Possible cluster DNS Server Found: %s", serverAddr)
49+
return true
50+
}
51+
return false
52+
}

cmd/wildcard/wildcard.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ func init() {
1313
}
1414

1515
var WildCardCmd = &cobra.Command{
16-
Use: "wild",
16+
Use: "wild",
17+
Aliases: []string{
18+
"w",
19+
},
1720
Short: "wild is a tool to abuse wildcard feature in kubernetes service discovery",
1821
Run: func(cmd *cobra.Command, args []string) {
1922
if command.Opts.Zone == "" {

main.go

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
_ "github.com/esonhugh/k8spider/cmd/neighbor"
88
_ "github.com/esonhugh/k8spider/cmd/service"
99
_ "github.com/esonhugh/k8spider/cmd/subnet"
10+
_ "github.com/esonhugh/k8spider/cmd/whereisdns"
1011
_ "github.com/esonhugh/k8spider/cmd/wildcard"
1112
)
1213

pkg/ip_utils.go

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package pkg
2+
3+
import (
4+
"encoding/binary"
5+
"fmt"
6+
"net"
7+
"strings"
8+
)
9+
10+
func ParseStringToIPNet(s string) (ipnet *net.IPNet, err error) {
11+
_, ipnet, err = net.ParseCIDR(s)
12+
return
13+
}
14+
15+
func ParseIPNetToIPs(ipv4Net *net.IPNet) (ips []net.IP) {
16+
// convert IPNet struct mask and address to uint32
17+
// network is BigEndian
18+
mask := binary.BigEndian.Uint32(ipv4Net.Mask)
19+
start := binary.BigEndian.Uint32(ipv4Net.IP)
20+
21+
// find the final address
22+
finish := (start & mask) | (mask ^ 0xffffffff)
23+
24+
// loop through addresses as uint32
25+
for i := start; i <= finish; i++ {
26+
// convert back to net.IP
27+
ip := make(net.IP, 4)
28+
binary.BigEndian.PutUint32(ip, i)
29+
ips = append(ips, ip)
30+
}
31+
return
32+
}
33+
34+
func IPtoPodHostName(ip, namespace string) string {
35+
return fmt.Sprintf("%s.%s.pod.%s", strings.ReplaceAll(ip, ".", "-"), namespace, Zone)
36+
}

pkg/query_utils.go

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package pkg
2+
3+
import (
4+
"context"
5+
"net"
6+
"time"
7+
8+
log "github.com/sirupsen/logrus"
9+
)
10+
11+
var (
12+
DnsTimeout = 2
13+
NetResolver = DefaultResolver()
14+
Zone string // Zone is the domain name of the cluster
15+
)
16+
17+
type SpiderResolver struct {
18+
dns string
19+
ctx context.Context
20+
r *net.Resolver
21+
}
22+
23+
func DefaultResolver() *SpiderResolver {
24+
ctx, _ := context.WithTimeout(context.Background(), time.Duration(DnsTimeout)*time.Second) // I don't think if a inside cluster dns query has more than 2s latency.
25+
return &SpiderResolver{
26+
dns: "<default-dns>",
27+
r: net.DefaultResolver,
28+
ctx: ctx,
29+
}
30+
}
31+
32+
func WarpDnsServer(dnsServer string) *SpiderResolver {
33+
ctx, _ := context.WithTimeout(context.Background(), time.Duration(DnsTimeout)*time.Second)
34+
return &SpiderResolver{
35+
dns: dnsServer,
36+
r: &net.Resolver{
37+
PreferGo: true,
38+
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
39+
d := net.Dialer{}
40+
return d.DialContext(ctx, network, dnsServer)
41+
},
42+
},
43+
ctx: ctx,
44+
}
45+
}
46+
47+
func (s *SpiderResolver) CurrentDNS() string {
48+
return s.dns
49+
}
50+
51+
func (s *SpiderResolver) PTRRecord(ip net.IP) []string {
52+
names, err := s.r.LookupAddr(s.ctx, ip.String())
53+
if err != nil {
54+
log.Debugf("LookupAddr failed: %v", err)
55+
return nil
56+
}
57+
return names
58+
}
59+
60+
func PTRRecord(ip net.IP) []string {
61+
return NetResolver.PTRRecord(ip)
62+
}
63+
64+
func (s *SpiderResolver) SRVRecord(svcDomain string) (string, []*net.SRV, error) {
65+
cname, srvs, err := s.r.LookupSRV(s.ctx, "", "", svcDomain)
66+
return cname, srvs, err
67+
}
68+
69+
func (s *SpiderResolver) CustomSRVRecord(svcDomain string, service, proto string) (string, []*net.SRV, error) {
70+
cname, srvs, err := s.r.LookupSRV(s.ctx, service, proto, svcDomain)
71+
return cname, srvs, err
72+
}
73+
74+
func SRVRecord(svcDomain string) (string, []*net.SRV, error) {
75+
return NetResolver.SRVRecord(svcDomain)
76+
}
77+
78+
func (s *SpiderResolver) ARecord(domain string) ([]net.IP, error) {
79+
return s.r.LookupIP(s.ctx, "ip", domain)
80+
}
81+
82+
func ARecord(domain string) (ips []net.IP, err error) {
83+
return NetResolver.ARecord(domain)
84+
}
85+
86+
func (s *SpiderResolver) TXTRecord(domain string) ([]string, error) {
87+
return s.r.LookupTXT(s.ctx, domain)
88+
}
89+
90+
func TXTRecord(domain string) (txts []string, err error) {
91+
return NetResolver.TXTRecord(domain)
92+
}

0 commit comments

Comments
 (0)