Is there anyway to retrieve the maximum numbers of IPv6 from a CIDR range? Currently I have this code:
package main
import (
"fmt"
"log"
"net"
)
func main() {
ip, ipnet, err := net.ParseCIDR("2001:200:905::/49")
var ips []string
if err != nil {
log.Fatal(err)
}
for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
ips = append(ips, ip.String())
}
fmt.Println(len(ips))
}
func inc(ip net.IP) {
for j := len(ip)-1; j>=0; j-- {
ip[j]++
if ip[j] > 0 {
break
}
}
}
But this process runs so slow. Is there any efficient way of retrieving the total number of ip addresses?
The IPAddress Go library can do this (get the count, starting point, end, or any address in the middle) with a few lines of polymorphic code that works with both IPv4 and IPv6 addresses. Repository here. Disclaimer: I am the project manager.
func details(addrStr string) {
addr := ipaddr.NewIPAddressString(addrStr).GetAddress()
lower, upper := addr.GetLower(), addr.GetUpper()
count := addr.GetCount()
fmt.Printf("%s has size %d,\n\tranging from %v to %v\n",
addr, count, lower, upper)
fmt.Println("\thundredth address is", addr.Increment(100))
}
Using your IPv6 example as well as an IPv4 subnet:
details("2001:200:905::/49")
details("192.168.10.0/24")
Output:
2001:200:905::/49 has size 604462909807314587353088,
ranging from 2001:200:905::/49 to 2001:200:905:7fff:ffff:ffff:ffff:ffff/49
hundredth address is 2001:200:905::64/49
192.168.10.0/24 has size 256,
ranging from 192.168.10.0/24 to 192.168.10.255/24
hundredth address is 192.168.10.100/24
Related
func getLocalIP() ([]string, error) {
addrs, err := net.InterfaceAddrs()
if err != nil {
return nil, err
}
IPs := make([]string, 0)
for _, a := range addrs {
if ipNet, ok := a.(*net.IPNet); ok && !ipNet.IP.IsLoopback() {
if ipNet.IP.To4() != nil {
IPs = append(IPs, ipNet.IP.To4().String())
}
}
}
return IPs, nil
}
func TestGetLocalIP() {
addrs, _ := getLocalIP()
for _, a := range addrs {
fmt.Println(a)
}
}
I used this,but it give me a list of ip address.
I just want to get my wifi local address,how to do that?
You need to know at least one of two pieces of information going in:
the name of the correct interface (typically en0 on a Mac, e.g., but YMMV)
the address for your wireless network, including the length of the mask - something like 192.168.0.0/16 or 192.168.0.0/24 is pretty common, but you'll have to figure this out ahead of time.
If you only know the interface name:
ifs, _ := net.Interfaces()
for _, ifi := range ifs {
if ifi.Name == "en0" { // Or whatever other filter you want
addrs, _ := ifi.Addresses()
for _, a := range addrs {
// Filter to get the one you want, typically unicast IP4
}
}
}
Still simpler:
if, _ := net.InterfaceByName("en0")
addrs, _ := if.Addresses()
for _, a := range addrs {
// As before, filter for the address you want
}
If you know the network address for your wireless network
// Loop over interfaces, get addrs, then loop over addresses and get IPs for those that have them
if ip.Mask(net.CIDRMask(16, 32)) == myNetworkAddress {
// The interface you got this IP from is probably your wifi interface
}
Which method to choose
Depending on the interface having a specific name is generally not going to be portable. So while my assumption was that you were just trying to get this working on your own workstation, if this is for something which needs to run across multiple hosts, you may need to start off at least with matching against the correct network address. There are other tricks as well - if you know e.g. that you are going to be running in a server farm in which every host has a NIC from manufacturer XXX, you can look up the MAC address and see if it comes from that manufacturer - you can try this out here. You can use other filters as well, but those are going to be pretty specific to your individual use case.
I am learning to use Golang to develop hacking tools through Blackhat-Go and port scan scanme.nmap.org on Windows and Linux while doing TCP scanning.Here's my code
package main
import (
"fmt"
"net"
"sort"
)
func worker(ports, result chan int) {
for port := range ports {
address := fmt.Sprintf("scanme.nmap.org:%d", port)
conn, err := net.Dial("tcp", address)
if err != nil {
result <- 0
continue
}
conn.Close()
result <- port
}
}
func main() {
ports := make(chan int, 100)
result := make(chan int)
var openport []int
for i := 0; i < cap(ports); i++ {
go worker(ports, result)
}
go func() {
for i := 0; i < 1024; i++ {
ports <- i
}
}()
for i := 0; i < 1024; i++ {
port := <-result
if port != 0 {
openport = append(openport, port)
}
}
close(ports)
close(result)
sort.Ints(openport)
for _, value := range openport {
fmt.Printf("%d open\n", value)
}
}
Running on Windows shows that port 25 is open.
22 open
25 open
80 open
110 open
However, port 25 is not detected on Linux.
22 open
80 open
110 open
I used NMAP to scan and found that the state of port 25 is Filtered.
25/tcp filtered smtp
Why is port 25 detected on Windows.
any help please.
I'm looking for a way to convert a netmask string into CIDR notation in Go.
For instance, "255.255.255.0" -> "/24"
I'm currently obtaining an IP address and the net mask string with the below logic, which may just be complicating things.
I've been perusing the net library trying to see if there is a different function to use to accomplish what I'd like, which is really just a IP address in CIDR notation:
192.168.1.2/24
var mgmtInterface *net.Interface
var err error
mgmtInterface, err = net.InterfaceByName("eth0")
if err != nil {
log.Println("Unable to find interface eth0, trying en0")
mgmtInterface, err = net.InterfaceByName("en0")
}
addrs, err := mgmtInterface.Addrs()
if err != nil {
log.Println("interface has no address")
}
for _, addr := range addrs {
var ip net.IP
var mask net.IPMask
switch v := addr.(type) {
case *net.IPNet:
ip = v.IP
mask = v.Mask
case *net.IPAddr:
ip = v.IP
mask = ip.DefaultMask()
}
if ip == nil {
continue
}
ip = ip.To4()
if ip == nil {
continue
}
// create the netmask
cleanMask := fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3])
}
This isn't very obvious at first, but:
addr := ip.To4()
sz, _ := net.IPV4Mask(addr[0], addr[1], addr[2], addr[3]).Size()
I'm not aware about existense of such function but it's easy to create one.
CIDR notation is just a count of set bits in netmask.
So, crude solution could be:
func cidr(netmask string) int {
var mask uint32
for idx, dotpart := range strings.Split(netmask, ".") {
part, _ := strconv.Atoi(dotpart)
mask = mask | uint32(part) << uint32(24-idx*8)
}
return len(fmt.Sprintf("%b", mask))
}
This is straightforward using the IPAddress Go library. Note that this code works equally well with both IPv4 and IPv6. Disclaimer: I am the project manager.
import (
"fmt"
"github.com/seancfoley/ipaddress-go/ipaddr"
)
func main() {
maskStr := "255.255.255.0"
pref := ipaddr.NewIPAddressString(maskStr).GetAddress().
GetBlockMaskPrefixLen(true)
fmt.Printf("prefix length for %s is %d", maskStr, pref.Len())
}
Output:
prefix length for 255.255.255.0 is 24
I am trying to play around with go to make some kind of port scanner using the stdlib. This is more of an exercise than anything else, so please don't comment on the logic involved.
Looking at the following code:
package main
import (
"flag"
"fmt"
"net"
"time"
"strings"
"strconv"
"log"
"sync"
)
var commonPorts = map[int]string {
21: "ftp",
22: "sftp",
80: "http",
110: "pop3",
143: "imap",
443: "https",
631: "ipp",
993: "imaps",
995: "pop3s",
}
type OP struct {
mu sync.Mutex
ports []string
}
func (o *OP) SafeAdd(port string) {
o.mu.Lock()
defer o.mu.Unlock()
o.ports = append(o.ports, port)
}
func worker(host string, port int) string {
address := fmt.Sprintf("%s:%d", host, port)
conn, err := net.DialTimeout("tcp", address, time.Second * 3)
if err != nil {
return ""; // is offline, cannot connect
}
conn.Close()
stringI := strconv.Itoa(port)
if name, ok := commonPorts[port]; ok {
stringI += fmt.Sprintf("(%s)", name)
}
return stringI
}
func processWithChannels(host string) <-chan string{
openPort := make(chan string, 1000)
var wg sync.WaitGroup
for i := 1; i <= 65535; i++ {
wg.Add(1)
go func(openPort chan string, host string, i int) {
defer wg.Done()
port := worker(host, i)
if port != "" {
openPort <- port
}
}(openPort, host, i)
}
wg.Wait()
close(openPort)
return openPort
}
func main() {
var host = flag.String("host", "127.0.0.1", "please insert the host")
var pType = flag.Int("type", 2, "please insert the type")
flag.Parse()
fmt.Printf("Scanning: %s...\n", *host)
if _, err := net.LookupHost(*host); err != nil {
log.Fatal(err)
}
openPorts := &OP{ports: []string{}};
if *pType == 1 {
ports := processWithChannels(*host);
for port := range ports {
openPorts.SafeAdd(port)
}
} else {
var wg sync.WaitGroup
for i := 1; i <= 65535; i++ {
wg.Add(1)
go func(o *OP, host string, i int){
defer wg.Done()
if port := worker(host, i); port != "" {
o.SafeAdd(port)
}
}(openPorts, *host, i)
}
wg.Wait()
}
if len(openPorts.ports) > 0 {
fmt.Printf("Following ports are opened: %s\n", strings.Join(openPorts.ports, ", "))
} else {
fmt.Printf("No open port on the host: %s!\n", *host)
}
}
There are two ways of starting a scan, either by using a buffered channel or by using sync.GroupWait and bail out once all the scans are done.
It seems to me that in this case, using sync.GroupWait makes more sense than using a buffered channel and loop through it till it's empty. However, using a buffered channel here, i don't see a way to detect that there's nothing else on the channel and that i should bail out from the for loop, except by using another sync.WaitGroup block.
I think my question is, in case i want to use the buffered channel solution only, how do i implement it properly so that i know when the processing is done so that i can proceed with the rest of the code? (don't suggest timeouts please).
Here's also a small benchmark with the two types, in case anyone interested:
MacBook-Pro:PortScanner c$ time ./PortScanner -host yahoo.com -type 1
Scanning: yahoo.com...
Following ports are opened: 80(http), 143(imap), 110(pop3), 995(pop3s), 993(imaps)
real 0m4.620s
user 0m1.193s
sys 0m1.284s
MacBook-Pro:PortScanner c$ time ./PortScanner -host yahoo.com -type 2
Scanning: yahoo.com...
Following ports are opened: 110(pop3), 80(http), 143(imap), 995(pop3s), 993(imaps)
real 0m4.055s
user 0m1.051s
sys 0m0.946s
The call to processWithChannels will hang if you need to put more than 1000 items into the channel. If you're going to use a buffered channel to hold all values until processing, there has to be enough capacity to accept all values.
If you are going to collect all values into a single slice, then there's no reason to use a channel, and your second solution is just fine.
If you want to "stream" the ports back as soon as possible, then you need something in between the two solutions
ports := make(chan string)
var wg sync.WaitGroup
for i := 1; i <= 65535; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
if port := worker(*host, i); port != "" {
ports <- port
}
}(i)
}
go func() {
wg.Wait()
close(ports)
}()
for port := range ports {
fmt.Println("PORT:", port)
}
This however is likely to run into problems, like missing open ports when you dial all 65535 ports at the same time. Here is one possible pattern to use a pool of workers to dial concurrently:
ports := make(chan string)
toScan := make(chan int)
var wg sync.WaitGroup
// make 100 workers for dialing
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for p := range toScan {
ports <- worker(*host, p)
}
}()
}
// close our receiving ports channel once all workers are done
go func() {
wg.Wait()
close(ports)
}()
// feed the ports to the worker pool
go func() {
for i := 1; i <= 65535; i++ {
toScan <- i
}
// signal the workers to stop
close(toScan)
}()
for port := range ports {
if port != "" {
fmt.Println("PORT:", port)
}
}
I'm considering to call net.IP.String(), strings.Split(ip, "."), some code to calculate all the corner cases and finally net.ParseIP(s). Is there a better way to this?. Below is the code of my current implementation (no special case handled).
package main
import (
"fmt"
"net"
"strconv"
"strings"
)
func main() {
ip := net.ParseIP("127.1.0.0")
next, err := NextIP(ip)
if err != nil {
panic(err)
}
fmt.Println(ip, next)
}
func NextIP(ip net.IP) (net.IP, error) {
s := ip.String()
sa := strings.Split(s, ".")
i, err := strconv.Atoi(sa[2])
if err != nil {
return nil, err
}
i++
sa[3] = strconv.Itoa(i)
s = strings.Join(sa, ".")
return net.ParseIP(s), nil
}
Just increment the last octet in the IP address
ip := net.ParseIP("127.1.0.0")
// make sure it's only 4 bytes
ip = ip.To4()
// check ip != nil
ip[3]++ // check for rollover
fmt.Println(ip)
//127.1.0.1
That however is technically incorrect, since the first address in the 127.1.0.1/8 subnet is 127.0.0.1. To get the true "first" address, you will also need an IPMask. Since you didn't specify one, you could use DefaultMask for IPv4 addresses (for IPv6 you can't assume a mask, and you must provide it).
http://play.golang.org/p/P_QWwRIBIm
ip := net.IP{192, 168, 1, 10}
ip = ip.To4()
if ip == nil {
log.Fatal("non ipv4 address")
}
ip = ip.Mask(ip.DefaultMask())
ip[3]++
fmt.Println(ip)
//192.168.1.1
If all you need is to compute the next IP address, the function nextIP() below will do the trick.
Usage:
// output is 1.0.1.0
fmt.Println(nextIP(net.ParseIP("1.0.0.255"), 1))
nextIP():
func nextIP(ip net.IP, inc uint) net.IP {
i := ip.To4()
v := uint(i[0])<<24 + uint(i[1])<<16 + uint(i[2])<<8 + uint(i[3])
v += inc
v3 := byte(v & 0xFF)
v2 := byte((v >> 8) & 0xFF)
v1 := byte((v >> 16) & 0xFF)
v0 := byte((v >> 24) & 0xFF)
return net.IPv4(v0, v1, v2, v3)
}
Playground: https://play.golang.org/p/vHrmftkVjn2
Gist: https://gist.github.com/udhos/b468fbfd376aa0b655b6b0c539a88c03
I would test against CIDR after the IP has been incremented, so overflows don't change the expected subnet.
func incrementIP(origIP, cidr string) (string, error) {
ip := net.ParseIP(origIP)
_, ipNet, err := net.ParseCIDR(cidr)
if err != nil {
return origIP, err
}
for i := len(ip) - 1; i >= 0; i-- {
ip[i]++
if ip[i] != 0 {
break
}
}
if !ipNet.Contains(ip) {
return origIP, errors.New("overflowed CIDR while incrementing IP")
}
return ip.String(), nil
}
I've encountered this problem just now, and I want to share my solution. It's not that efficient but solves the problem in a few lines.
func nextIP(ip net.IP) net.IP {
// Convert to big.Int and increment
ipb := big.NewInt(0).SetBytes([]byte(ip))
ipb.Add(ipb, big.NewInt(1))
// Add leading zeros
b := ipb.Bytes()
b = append(make([]byte, len(ip)-len(b)), b...)
return net.IP(b)
}
This is straightforward using the IPAddress Go library, works for both IPv4 and IPv6, and handles corner cases. Disclaimer: I am the project manager.
import (
"fmt"
"github.com/seancfoley/ipaddress-go/ipaddr"
)
func main() {
fmt.Println(increment("127.0.0.1"))
fmt.Println(increment("127.0.0.255"))
fmt.Println(increment("::1"))
fmt.Println(increment("255.255.255.255"))
}
func increment(addrString string) *ipaddr.IPAddress {
addr := ipaddr.NewIPAddressString(addrString).GetAddress()
return addr.Increment(1)
}
Output:
127.0.0.2
127.0.1.0
::2
<nil>