Skip to content

Commit

Permalink
Add dual-stack IP support (#610)
Browse files Browse the repository at this point in the history
* Add dual-stack IP support.

* Add dual-stack IP support to compatible providers.
  • Loading branch information
v0ctor authored Jan 15, 2025
1 parent 95682e0 commit 9ecf209
Show file tree
Hide file tree
Showing 20 changed files with 211 additions and 69 deletions.
4 changes: 4 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,12 @@ type Resource struct {
ID string `json:"id,omitempty"`
// PublicIPv4 is the public ipv4 address of the instance.
PublicIPv4 string `json:"public_ipv4,omitempty"`
// PublicIPv6 is the public ipv6 address of the instance.
PublicIPv6 string `json:"public_ipv6,omitempty"`
// PrivateIpv4 is the private ipv4 address of the instance
PrivateIpv4 string `json:"private_ipv4,omitempty"`
// PrivateIpv6 is the private ipv6 address of the instance
PrivateIpv6 string `json:"private_ipv6,omitempty"`
// DNSName is the DNS name of the resource
DNSName string `json:"dns_name,omitempty"`
}
Expand Down
38 changes: 38 additions & 0 deletions internal/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,15 @@ func (r *Runner) Enumerate() {
if instance.PrivateIpv4 != "" {
ipCount++
}
if instance.PrivateIpv6 != "" {
ipCount++
}
if instance.PublicIPv4 != "" {
ipCount++
}
if instance.PublicIPv6 != "" {
ipCount++
}
gologger.Silent().Msgf("%s", builder.String())
builder.Reset()
}
Expand All @@ -137,6 +143,14 @@ func (r *Runner) Enumerate() {
builder.Reset()
gologger.Silent().Msgf("%s", instance.PublicIPv4)
}
if instance.PublicIPv6 != "" {
ipCount++
builder.WriteString(instance.PublicIPv6)
builder.WriteRune('\n')
output.WriteString(builder.String()) //nolint
builder.Reset()
gologger.Silent().Msgf("%s", instance.PublicIPv6)
}
if instance.PrivateIpv4 != "" && !r.options.ExcludePrivate {
ipCount++
builder.WriteString(instance.PrivateIpv4)
Expand All @@ -145,6 +159,14 @@ func (r *Runner) Enumerate() {
builder.Reset()
gologger.Silent().Msgf("%s", instance.PrivateIpv4)
}
if instance.PrivateIpv6 != "" && !r.options.ExcludePrivate {
ipCount++
builder.WriteString(instance.PrivateIpv6)
builder.WriteRune('\n')
output.WriteString(builder.String()) //nolint
builder.Reset()
gologger.Silent().Msgf("%s", instance.PrivateIpv6)
}
continue
}

Expand All @@ -164,6 +186,14 @@ func (r *Runner) Enumerate() {
builder.Reset()
gologger.Silent().Msgf("%s", instance.PublicIPv4)
}
if instance.PublicIPv6 != "" {
ipCount++
builder.WriteString(instance.PublicIPv6)
builder.WriteRune('\n')
output.WriteString(builder.String()) //nolint
builder.Reset()
gologger.Silent().Msgf("%s", instance.PublicIPv6)
}
if instance.PrivateIpv4 != "" && !r.options.ExcludePrivate {
ipCount++
builder.WriteString(instance.PrivateIpv4)
Expand All @@ -172,6 +202,14 @@ func (r *Runner) Enumerate() {
builder.Reset()
gologger.Silent().Msgf("%s", instance.PrivateIpv4)
}
if instance.PrivateIpv6 != "" && !r.options.ExcludePrivate {
ipCount++
builder.WriteString(instance.PrivateIpv6)
builder.WriteRune('\n')
output.WriteString(builder.String()) //nolint
builder.Reset()
gologger.Silent().Msgf("%s", instance.PrivateIpv6)
}
}
logBuilder := &strings.Builder{}
if hostsCount != 0 {
Expand Down
23 changes: 15 additions & 8 deletions pkg/providers/arvancloud/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,21 @@ func (d *dnsProvider) GetResource(ctx context.Context) (*schema.Resources, error

for _, record := range arrayRecord.GetValue() {
if v, ok := record.(map[string]interface{}); ok {
list.Append(&schema.Resource{
Public: true,
Provider: providerName,
DNSName: fmt.Sprintf("%s.%s", arrayRecord.GetName(), domain.GetName()),
PublicIPv4: v["ip"].(string),
ID: d.id,
Service: d.name(),
})
resource := &schema.Resource{
Public: true,
Provider: providerName,
DNSName: fmt.Sprintf("%s.%s", arrayRecord.GetName(), domain.GetName()),
ID: d.id,
Service: d.name(),
}

if arrayRecord.GetType() == "a" {
resource.PublicIPv4 = v["ip"].(string)
} else {
resource.PublicIPv6 = v["ip"].(string)
}

list.Append(resource)
} else {
return nil, errors.Wrap(err, fmt.Sprintf("could not get ip for `%s` record", arrayRecord.GetName()))
}
Expand Down
14 changes: 8 additions & 6 deletions pkg/providers/aws/ecs.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,25 +125,27 @@ func (ep *ecsProvider) listECSResources(ecsClient *ecs.ECS, ec2Client *ec2.EC2)

for _, reservation := range describeInstancesOutput.Reservations {
for _, instance := range reservation.Instances {
privateIP := aws.StringValue(instance.PrivateIpAddress)
publicIP := aws.StringValue(instance.PublicIpAddress)
ip4 := aws.StringValue(instance.PublicIpAddress)
ip6 := aws.StringValue(instance.Ipv6Address)
privateIp4 := aws.StringValue(instance.PrivateIpAddress)

if privateIP != "" {
if privateIp4 != "" {
resource := &schema.Resource{
ID: aws.StringValue(instance.InstanceId),
Provider: "aws",
PrivateIpv4: privateIP,
PrivateIpv4: privateIp4,
Public: false,
Service: ep.name(),
}
list.Append(resource)
}

if publicIP != "" {
if ip4 != "" || ip6 != "" {
resource := &schema.Resource{
ID: aws.StringValue(instance.InstanceId),
Provider: "aws",
PublicIPv4: publicIP,
PublicIPv4: ip4,
PublicIPv6: ip6,
Public: true,
Service: ep.name(),
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/providers/aws/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func (i *instanceProvider) getEC2Resources(ec2Client *ec2.EC2) (*schema.Resource
for _, reservation := range resp.Reservations {
for _, instance := range reservation.Instances {
ip4 := aws.StringValue(instance.PublicIpAddress)
ip6 := aws.StringValue(instance.Ipv6Address)
privateIp4 := aws.StringValue(instance.PrivateIpAddress)

if privateIp4 != "" {
Expand All @@ -79,6 +80,7 @@ func (i *instanceProvider) getEC2Resources(ec2Client *ec2.EC2) (*schema.Resource
ID: i.options.Id,
Provider: providerName,
PublicIPv4: ip4,
PublicIPv6: ip6,
Public: true,
Service: i.name(),
})
Expand Down
5 changes: 5 additions & 0 deletions pkg/providers/aws/lightsail.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ func (l *lightsailProvider) listListsailResources(lsClient *lightsail.Lightsail)
Public: publicIPv4 != "",
Service: l.name(),
}

if len(instance.Ipv6Addresses) > 0 {
resource.PublicIPv6 = aws.StringValue(instance.Ipv6Addresses[0])
}

list.Append(resource)
}
if aws.StringValue(resp.NextPageToken) == "" {
Expand Down
26 changes: 17 additions & 9 deletions pkg/providers/aws/route53.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ func (r *route53Provider) listResourcesByZone(zones []*route53.HostedZone, clien
}
name := strings.TrimSuffix(*item.Name, ".")

var ip4 string
var record string
if len(item.ResourceRecords) >= 1 {
ip4 = aws.StringValue(item.ResourceRecords[0].Value)
record = aws.StringValue(item.ResourceRecords[0].Value)
}
list.Append(&schema.Resource{
ID: r.options.Id,
Expand All @@ -99,13 +99,21 @@ func (r *route53Provider) listResourcesByZone(zones []*route53.HostedZone, clien
Provider: providerName,
Service: r.name(),
})
list.Append(&schema.Resource{
ID: r.options.Id,
Public: public,
PublicIPv4: ip4,
Provider: providerName,
Service: r.name(),
})

resource := &schema.Resource{
ID: r.options.Id,
Public: public,
Provider: providerName,
Service: r.name(),
}

if *item.Type == "A" {
resource.PublicIPv4 = record
} else if *item.Type == "AAAA" {
resource.PublicIPv6 = record
}

list.Append(resource)
}
if aws.BoolValue(sets.IsTruncated) && *sets.NextRecordName != "" {
req.SetStartRecordName(*sets.NextRecordName)
Expand Down
22 changes: 15 additions & 7 deletions pkg/providers/azure/publicips.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,21 @@ func (pip *publicIPProvider) GetResource(ctx context.Context) (*schema.Resources
if ip.IPAddress == nil {
continue
}
list.Append(&schema.Resource{
Provider: providerName,
PublicIPv4: *ip.IPAddress,
ID: pip.id,
Public: true,
Service: pip.name(),
})

resource := &schema.Resource{
Provider: providerName,
ID: pip.id,
Public: true,
Service: pip.name(),
}

if ip.PublicIPAddressVersion == network.IPv4 {
resource.PublicIPv4 = *ip.IPAddress
} else {
resource.PublicIPv6 = *ip.IPAddress
}

list.Append(resource)
}
return list, nil
}
Expand Down
15 changes: 11 additions & 4 deletions pkg/providers/azure/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,20 @@ func (d *vmProvider) GetResource(ctx context.Context) (*schema.Resources, error)
continue
}

list.Append(&schema.Resource{
resource := &schema.Resource{
Provider: providerName,
PublicIPv4: *publicIP.IPAddress,
ID: d.id,
PrivateIpv4: *privateIP,
Service: d.name(),
})
Service: d.name(),
}

if publicIP.PublicIPAddressVersion == network.IPv4 {
resource.PublicIPv4 = *publicIP.IPAddress
} else {
resource.PublicIPv6 = *publicIP.IPAddress
}

list.Append(resource)
}
}
}
Expand Down
22 changes: 15 additions & 7 deletions pkg/providers/cloudflare/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,21 @@ func (d *dnsProvider) GetResource(ctx context.Context) (*schema.Resources, error
if record.Type == "CNAME" {
continue
}
list.Append(&schema.Resource{
Public: true,
Provider: providerName,
PublicIPv4: record.Content,
ID: d.id,
Service: d.name(),
})

resource := &schema.Resource{
Public: true,
Provider: providerName,
ID: d.id,
Service: d.name(),
}

if record.Type == "A" {
resource.PublicIPv4 = record.Content
} else {
resource.PublicIPv6 = record.Content
}

list.Append(resource)
}
}
return list, nil
Expand Down
2 changes: 2 additions & 0 deletions pkg/providers/digitalocean/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func (d *instanceProvider) GetResource(ctx context.Context) (*schema.Resources,

for _, droplet := range droplets {
ip4, _ := droplet.PublicIPv4()
ip6, _ := droplet.PublicIPv6()
privateIP4, _ := droplet.PrivateIPv4()

if privateIP4 != "" {
Expand All @@ -44,6 +45,7 @@ func (d *instanceProvider) GetResource(ctx context.Context) (*schema.Resources,
Provider: providerName,
ID: d.id,
PublicIPv4: ip4,
PublicIPv6: ip6,
Public: true,
Service: d.name(),
})
Expand Down
23 changes: 15 additions & 8 deletions pkg/providers/gcp/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,21 @@ func (d *cloudDNSProvider) parseRecordsForResourceSet(r *dns.ResourceRecordSetsL
}

for _, data := range resource.Rrdatas {
list.Append(&schema.Resource{
DNSName: resource.Name,
Public: true,
PublicIPv4: data,
ID: d.id,
Provider: providerName,
Service: d.name(),
})
dst := &schema.Resource{
DNSName: resource.Name,
Public: true,
ID: d.id,
Provider: providerName,
Service: d.name(),
}

if resource.Type == "A" {
dst.PublicIPv4 = data
} else if resource.Type == "AAAA" {
dst.PublicIPv6 = data
}

list.Append(dst)
}
}
return list
Expand Down
3 changes: 2 additions & 1 deletion pkg/providers/gcp/vms.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ func (d *cloudVMProvider) GetResource(ctx context.Context) (*schema.Resources, e
Public: true,
Provider: providerName,
PublicIPv4: cfg.NatIP,
Service: d.name(),
PublicIPv6: cfg.ExternalIpv6,
Service: d.name(),
})
}
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/providers/hetzner/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ func (p *instanceProvider) GetResource(ctx context.Context) (*schema.Resources,
Provider: providerName,
ID: p.id,
PublicIPv4: server.PublicNet.IPv4.IP.String(),
PublicIPv6: server.PublicNet.IPv6.IP.String(),
Public: true,
Service: p.name(),
Service: p.name(),
})
}
for _, privateNet := range server.PrivateNet {
Expand Down
1 change: 1 addition & 0 deletions pkg/providers/linode/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func (d *instanceProvider) GetResource(ctx context.Context) (*schema.Resources,
list.Append(&schema.Resource{
Provider: providerName,
PublicIPv4: ip4,
PublicIPv6: inst.IPv6,
ID: d.id,
Public: ip4 != "",
Service: d.name(),
Expand Down
Loading

0 comments on commit 9ecf209

Please sign in to comment.