Sending UDPv6 locally in golang - go

I need to send a UDPv6 datagram being able to track this message by a local receiver (or via tcpdump).
daddr, err = net.ResolveUDPAddr("udp6", "[address]:port")
if err != nil {
return err
}
conn, err := net.DialUDP("udp6", nil, daddr)
if err != nil {
return err
}
defer conn.Close()
conn.Write(...)
Unlike IPv4 this code doesn't work with IPv6. For example, when I try to send a datagram to a multicast address, e.g. to [FF01::DB8:0:0]:5000, I get connect: invalid argument. The same happens when I try to send it to [fe80::20c:29ff:fee1:d66]:5000 (my IPv6 address according to ifconfig).

In both cases (link-local and interface-local multicast) you have forgotten to specify the scope ID. Without this, it is impossible to determine which interface to use, and you get an Invalid argument error from the operating system.
net.UDPAddr uses the Zone field to store the scope ID. You need to ensure that you have provided one, either by setting Zone explicitly or by using the percent-suffix notation.

Related

How I can receive data for ever from TCP server

I try to create TCP client to receive data from TCP server,
but after server sending data only I receive data one even if server send many data, and I want to receive data forever, and I don't know what is my problem,and
Client:
func main() {
tcpAddr := "localhost:3333"
conn, err := net.DialTimeout("tcp", tcpAddr, time.Second*7)
if err != nil {
log.Println(err)
}
defer conn.Close()
// conn.Write([]byte("Hello World"))
connBuf := bufio.NewReader(conn)
for {
bytes, err := connBuf.ReadBytes('\n')
if err != nil {
log.Println("Rrecv Error:", err)
}
if len(bytes) > 0 {
fmt.Println(string(bytes))
}
time.Sleep(time.Second * 2)
}
}
I'm following this example to create TCP test server
Server:
// Handles incoming requests.
func handleRequest(conn net.Conn) {
// Make a buffer to hold incoming data.
buf := make([]byte, 1024)
// Read the incoming connection into the buffer.
_, err := conn.Read(buf)
if err != nil {
fmt.Println("Error reading:", err.Error())
}
fmt.Println(buf)
// Send a response back to person contacting us.
var msg string
fmt.Scanln(&msg)
conn.Write([]byte(msg))
// Close the connection when you're done with it.
conn.Close()
}
Read requires a Write on the other side of the connection
want to receive data forever
Then you have to send data forever. There's a for loop on the receiving end, but no looping on the sending end. The server writes its message once and closes the connection.
Server expects to get msg from client but client doesn't send it
// conn.Write([]byte("Hello World"))
That's supposed to provide the msg value to the server
_, err := conn.Read(buf)
So those two lines don't match.
Client expects a newline but server isn't sending one
fmt.Scanln expects to put each whitespace separated value into the corresponding argument. It does not capture the whitespace. So:
Only up to the first whitespace of what you type into server's stdin will be stored in msg
Newline will not be stored in msg.
But your client is doing
bytes, err := connBuf.ReadBytes('\n')
The \n never comes. The client never gets done reading that first msg.
bufio.NewScanner would be a better way to collect data from stdin, since you're likely to want to capture whitespace as well. Don't forget to append the newline to each line of text you send, because the client expects it!
Working code
I put these changes together into a working example on the playground. To get it working in that context, I had to make a few other changes too.
Running server and client in the same process
Hard coded 3 clients so the program ended in limited amount of time
Hard coded 10 receives in the client so program can end
Hard coded 3 server connections handled so program can end
Removed fmt.Scanln and have server just return the original message sent (because playground provides no stdin mechanism)
Should be enough to get you started.

False positives during asynchronous TCP scanning through the Socks5 Proxy relay

I am learning golang and wanted to build a TCP port scanner with SOCKS5 proxies as a relay for mass scanning.
Although all of the S5 proxies are being checked for every target scan, sometimes there are some False positives - and I cannot find the reason why.
Preparing proxyDialer:
func create_socks5_tcp_dialer(socks5_addr string) proxy.Dialer {
//socks5_dialer_tcp, err := proxy.SOCKS5("tcp", socks5_addr, nil, proxy.Direct)
socks5_dialer_tcp, err := proxy.SOCKS5("tcp", socks5_addr, nil, &net.Dialer{Timeout: 5 * time.Second, KeepAlive: 5 * time.Second})
if err != nil {
fmt.Println("Error connecting to proxy:", err)
}
return socks5_dialer_tcp
}
Validating socks5 address:
func socks5_validator(socks5_addr, vps_opened, vps_closed string) (bool, string) {
/* Check if SOCKS5 proxy is valid.
1. Connect to the open port on the server under my control using proxy.
2. Connect to the closed port on the server under my control using proxy.
- If both checks are true then, SOCKS5 proxy is considered as valid.
- If one of the check is false, SOCKS5 proxy is considered as invalid.
3. Returns true/false and s5_addr.
*/
// Create SOCKS5 dialer
socks5_dialer_tcp := create_socks5_tcp_dialer(socks5_addr)
// Make connection using SOCKS5 proxy to the opened port on the vps.
conn_1, err := socks5_dialer_tcp.Dial("tcp", vps_opened)
// If it was successful and not generate any error then check1 is passed.
if err == nil {
//fmt.Println("CHECK 1: PASSED")
conn_1.Close()
// If error was generated then check is not passed and do not make check2.
} else {
//fmt.Println("CHECK 1: NOT PASSED")
return false, socks5_addr
}
// Make connection using SOCKS5 proxy to the closed port on the vps.
conn_2, err := socks5_dialer_tcp.Dial("tcp", vps_closed)
// If it was unsuccessful and error was generated then check2 is passed.
if err != nil {
//fmt.Println("CHECK 2: PASSED")
// If both checks were passed then return false.
return true, socks5_addr
// If error was not generated then check2 is not passed.
} else {
//fmt.Println("CHECK 2: NOT PASSED")
conn_2.Close()
return false, socks5_addr
}
}
Port scanning
s5_dialer_tcp := create_socks5_tcp_dialer(socks5_addr)
// Scan target using s5
conn, err := s5_dialer_tcp.Dial("tcp", target)
if err != nil {
//open
} else {
//closed
}
My question is:
Do I correctly scan TCP services through the SOCKS5 proxy and do I validate this proxy properly?
Link to the full code:
https://github.com/Karmaz95/crimson_prober
I don't think that these are actual false positives. Instead you are having the wrong assumptions of how these proxies will work: You assume that if the single check for a specific port open (connect success) and a specific port closed (connect failure) on a specific server at a specific time succeeds, then the proxy can be used to reliably check many arbitrary ports on arbitrary servers at arbitrary times.
This assumption is likely not valid, especially given that you seem to use proxies which are outside of your control.
A common behavior of such proxies is that they provide only restricted access, i.e. common ports like HTTP and HTTPS will work while other ports will be blocked. Proxies might also employ rate limiting, so they will simply deny access through the proxy after a while. And free proxies available in some lists often cease to work after a while.

How to drop a UDP connection between server and client from server side in Golang?

I'm trying to find a standard way to close a connection between a client and server in a UDP connection.
Currently, I came up with the following solution, however, I'm not sure whether this is an idiomatic way or not?
Basically what I'm doing here on the server-side (handleClient function) is to conn.WriteTo(nil, Addr) which write nil to the UDP address. on the client side I check if the read() function retrieved any data or not, in case the number of the reading byte is zero, the client gives up on reading.
if n ==0 || err != nil {
break
}
Here is my simplified Server.go file:
func handleClient(conn *net.UDPConn) {
b := make([]byte, 1024)
n, Addr, err := conn.ReadFrom(b[0:])
if err != nil {
panic(err)
}
fmt.Println("read: ", n, " bytes", Addr.String())
// write the data back to the client, just for debug purpose
conn.WriteTo(b[0:n], Addr)
// let the client know that server has no more data
conn.WriteTo(nil, Addr)
}
And this is my client.go file
conn, err := net.Dial("udp", ":14000")
if err != nil {
panic(err)
}
defer conn.Close()
conn.Write([]byte("I'm client "))
for {
b := make([]byte, 512)
n, err := conn.Read(b)
if n ==0 || err != nil {
fmt.Println(">", n, err)
break
}
fmt.Println(string(b))
}
fmt.Println("finished.")
There is no standard way to do this. UDP is a stateless protocol so there is no "connection" like you would have with a TCP connection. DNS for example has no concept of a state, a client sends a request and the server will respond, no state is maintained, this is usually the selling point of UDP.
The applications are responsible for maintain state, so if you want a stateful protocol on top of UDP you also have to handle closing such a connection yourself. You might take inspiration from FTP or TFTP on how to implement this. Or consider using a stateful transport layer protocol like TCP or QUIC to handle stateful connections for you.

How to use VPN(pptp) with golang net package?

I've bound several vpn on the server which is ppp0 ~ ppp4.
Now comes the problem.I want to start 5 progresses each one use the difference network interface.
proc0 -> ppp0
proc1 -> ppp1
proc2 -> ppp2
proc3 -> ppp3
proc4 -> ppp4
I now how to do this with c language.Just use setsockopt with parameter SO_BINDTODEVICE.
But how to do this with net package in golang?
You probably want net.Interfaces() to get a slice of net.Interface() representing the network interfaces on your system, or, as you know the interface names, you can use net.InterfaceByName() to get a particular net.Interface.
ppp0, err := net.InterfaceByName("ppp0")
You can then call Interface.Addrs() on the returned net.Interface and get the interface's IP address(es).
addrs, err := ppp0.Addrs()
You can then use the desired address in the rest of your code (probably using net.ListenIP or net.DialIP.
addr, err := net.ResolveIPAddr("ip4", addrs[0])
// check err
conn, err := net.ListenIP("ip4:pptp", addr)
// check err, then do stuff with conn
Regarding doing this for more than one interface concurrently, you can launch a goroutine for each listener / interface, and move the traffic over channels, but this really depends on what you want to do. (are you just logging the data, sending the data, modifying the data etc.)
The dialer's LocalAddr doesn't work for ppp interfaces, we should set the SOL_SOCKET flag to socket using setsockopt, for go 1.11+ you can create a dialer like this
dialer := net.Dialer{
Control: func(network, address string, c syscall.RawConn) error {
return c.Control(func(fd uintptr) {
err := syscall.SetsockoptString(int(fd), syscall.SOL_SOCKET, 25, "ppp0")
if err != nil {
log.Printf("control: %s", err)
return
}
})
},
}
// use the dialer

running ip4 server on a Mac

I'm using some code from Jan Newmarch's book on Go to run a daytime server on my mac. It uses this code
func main() {
service := ":1200"
tcpAddr, err := net.ResolveTCPAddr("ip4", service)
checkError(err)
listener, err := net.ListenTCP("tcp", tcpAddr)
checkError(err)
however, when I run it (on a Mac), I get this error
Fatal error: unknown network ip4
Is there anything other than ip4 that I can include in this code to avoid that error?
tcpAddr, err := net.ResolveTCPAddr("ip4", service)
Note, I also tried ip6 and got the same error.
According to the documentation for ResolveTCPAddr the only valid values for the net arg are "tcp", "tcp4" and "tcp6"
I suspect you're getting mixed up between ResolveTCPAddr and ResolveIPAddr
"ip4" isn't a valid network for ResolveTCPAddr (source).
Use ResolveIPAddr for resolving a general IP address.
"ip4" is not a valid string
See the Documentation for ResolveTCPAddr
ResolveTCPAddr parses addr as a TCP address of the form "host:port" or
"[ipv6-host%zone]:port" and resolves a pair of domain name and port
name on the network net, which must be "tcp", "tcp4" or "tcp6". A
literal address or host name for IPv6 must be enclosed in square
brackets, as in "[::1]:80", "[ipv6-host]:http" or
"[ipv6-host%zone]:80".
And the code:
func ResolveTCPAddr(net, addr string) (*TCPAddr, error) {
switch net {
case "tcp", "tcp4", "tcp6":
case "": // a hint wildcard for Go 1.0 undocumented behavior
net = "tcp"
default:
return nil, UnknownNetworkError(net)
}
a, err := resolveInternetAddr(net, addr, noDeadline)
if err != nil {
return nil, err
}
return a.toAddr().(*TCPAddr), nil
}

Resources