Cannot receive response packets from multicast server in golang - go

I setup a udp server listening multicast trafic, and create a client to sent test packet. When the server receives the package, it will send a response. Everything is ok, except the client cannot receive the packet from the server. Why?
package main
import (
"log"
"net"
"os"
"time"
"golang.org/x/net/ipv4"
)
func SetupMulticast(ifn, addr string) {
ifi, err := net.InterfaceByName(ifn)
if err != nil {
log.Fatal(err)
}
//server
c, err := net.ListenPacket("udp4", addr)
if err != nil {
log.Fatal(err)
}
log.Printf("listen ad:%s\n", addr)
p := ipv4.NewPacketConn(c)
gAddr, err2 := net.ResolveUDPAddr("udp4", addr)
if err2 != nil {
log.Fatal(err2)
}
if err := p.JoinGroup(ifi, gAddr); err != nil {
log.Fatal(err)
}
if err := p.SetControlMessage(ipv4.FlagDst|ipv4.FlagSrc, true); err != nil {
log.Fatal(err)
}
go func() {
b := make([]byte, 1500)
for {
n, cm, src, err := p.ReadFrom(b)
if err != nil {
break
}
log.Println("receive:", string(b[:n]), cm.Dst.IsMulticast(), cm.Dst)
if n2, err := p.WriteTo([]byte("world!"), nil, src); err != nil {
log.Printf("fail to write back:%v\n", err)
} else {
log.Printf("write back addr: %s length:%d\n", src, n2)
}
}
}()
//client
if conn, err2 := net.DialUDP("udp4", nil /*src*/, gAddr); err2 != nil {
log.Fatal(err)
} else {
go func() {
for {
log.Println("write hello...")
conn.Write([]byte("hello"))
time.Sleep(time.Second * 2)
}
}()
go func() {
b2 := make([]byte, 1500)
for {
n, err := conn.Read(b2)
if err != nil {
log.Panic(err)
}
log.Printf("sender received response:%s\n", string(b2[:n]))
}
}()
}
}
func main() {
If := os.Args[1] //ens33
Addr := os.Args[2] //224.0.0.248:1025
SetupMulticast(If, Addr)
for {
}
}
And the output:
2022/08/17 22:53:53 listen ad:224.0.0.248:1025
2022/08/17 22:53:53 write hello...
2022/08/17 22:53:53 receive: hello true 224.0.0.248
2022/08/17 22:53:53 write back addr: 192.168.19.131:43925 length:6
2022/08/17 22:53:55 write hello...
2022/08/17 22:53:55 receive: hello true 224.0.0.248
2022/08/17 22:53:55 write back addr: 192.168.19.131:43925 length:6
From the logs, there are no any "sender received response" record. I don't know why?

Related

Golang socks5 proxy client

I'm trying to make a proxy:
I need to listen to port 1080 (socks 5), and complete a request to a destination using an external ip:port socks 5, I managed to open this connection with the external ip, but I don't know how I could complete the request to the target destination using that external ip.
could someone help me with this?
package main
import (
"bufio"
"errors"
"fmt"
"io"
"log"
"net"
)
const (
ConnectCommand = uint8(1)
BindCommand = uint8(2)
AssociateCommand = uint8(3)
ipv4Address = uint8(1)
fqdnAddress = uint8(3)
ipv6Address = uint8(4)
)
type AddrSpec struct {
FQDN string
IP net.IP
Port int
}
func main() {
l, err := net.Listen("tcp", "127.0.0.1:1080")
if err != nil {
fmt.Print(err)
}
defer l.Close()
for {
conn, err := l.Accept()
if err != nil {
fmt.Print(err)
}
go handle(conn)
}
}
func handle(conn net.Conn) {
defer func() {
_ = conn.Close()
}()
bufConn := bufio.NewReader(conn)
version := []byte{0}
if _, err := bufConn.Read(version); err != nil {
log.Fatalf("cannot read version: %s", err.Error())
}
if version[0] != uint8(5) {
log.Fatalf("unsupported SOCKS version: %v", version)
}
socks5ExternalConn, err := net.Dial("tcp", externalSOCKS5Proxy())
if err != nil {
log.Printf("Connection error: %s", err.Error())
}
dest, err := readAddrSpec(bufConn)
if err != nil {
}
// how i can send request to server with external conn?
}
func externalSOCKS5Proxy() string {
return "externalip:externalport"
}
func readAddrSpec(r io.Reader) (*AddrSpec, error) {
d := &AddrSpec{}
// Get the address type
addrType := []byte{0}
if _, err := r.Read(addrType); err != nil {
return nil, err
}
// Handle on a per type basis
switch addrType[0] {
case ipv4Address:
addr := make([]byte, 4)
if _, err := io.ReadAtLeast(r, addr, len(addr)); err != nil {
return nil, err
}
d.IP = net.IP(addr)
case ipv6Address:
addr := make([]byte, 16)
if _, err := io.ReadAtLeast(r, addr, len(addr)); err != nil {
return nil, err
}
d.IP = net.IP(addr)
case fqdnAddress:
if _, err := r.Read(addrType); err != nil {
return nil, err
}
addrLen := int(addrType[0])
fqdn := make([]byte, addrLen)
if _, err := io.ReadAtLeast(r, fqdn, addrLen); err != nil {
return nil, err
}
d.FQDN = string(fqdn)
default:
return nil, errors.New("unrecognizedAddrType")
}
// Read the port
port := []byte{0, 0}
if _, err := io.ReadAtLeast(r, port, 2); err != nil {
return nil, err
}
d.Port = (int(port[0]) << 8) | int(port[1])
return d, nil
}

go udp requests (packet) loss

i wrote simple server and client for tcp and udp connection
package main
//server.go
import (
"fmt"
"net"
"os"
"os/signal"
"syscall"
)
func main() {
tcp := 0
udp := 0
defer func(o, t *int) {
fmt.Println(*o, *t)
}(&tcp, &udp)
go func() {
l, err := net.ListenTCP("tcp", &net.TCPAddr{
IP: net.ParseIP("0.0.0.0"),
Port: 3000,
})
if err != nil {
panic(err)
}
b := make([]byte, 24)
for {
conn, err := l.Accept()
if err != nil {
continue
}
n, err := conn.Read(b)
if err != nil {
continue
}
r := string(b[:n])
if r == "close" {
conn.Close()
break
} else {
_, err = conn.Write([]byte("pong"))
if err != nil {
continue
}
}
conn.Close()
tcp++
}
l.Close()
}()
go func() {
conn, err := net.ListenUDP("udp", &net.UDPAddr{
IP: net.ParseIP("0.0.0.0"),
Port: 3000,
})
if err != nil {
panic(err)
}
b := make([]byte, 24)
for {
n, addr, err := conn.ReadFromUDP(b)
if err != nil {
continue
}
r := string(b[:n])
if r == "close" {
break
} else {
_, err = conn.WriteToUDP([]byte("pong"), addr)
if err != nil {
continue
}
}
udp++
}
conn.Close()
}()
signals := make(chan os.Signal, 1)
signal.Notify(signals, os.Interrupt, syscall.SIGTERM)
<-signals
}
package main
//client.go
import (
"fmt"
"net"
"os"
"os/signal"
"strconv"
"sync/atomic"
"syscall"
"time"
)
func main() {
t := "tcp"
m := "ping"
c := 1
if len(os.Args) > 1 {
t = os.Args[1]
}
if len(os.Args) > 2 {
m = os.Args[2]
}
if len(os.Args) > 3 {
c, _ = strconv.Atoi(os.Args[3])
}
tcp := int64(0)
udp := int64(0)
defer func(o, t *int64) {
fmt.Println(*o, *t)
}(&tcp, &udp)
if c == 1 {
if t == "tcp" {
addr, err := net.ResolveTCPAddr("tcp", ":3000")
if err != nil {
panic(err)
}
conn, err := net.DialTCP("tcp", nil, addr)
if err != nil {
panic(err)
}
_, err = conn.Write([]byte(m))
if err != nil {
panic(err)
}
tcp++
}
if t == "udp" {
addr, err := net.ResolveUDPAddr("udp", ":3000")
if err != nil {
panic(err)
}
conn, err := net.DialUDP("udp", nil, addr)
if err != nil {
panic(err)
}
_, err = conn.Write([]byte(m))
if err != nil {
panic(err)
}
udp++
}
os.Exit(0)
}
for i := 0; i < c; i++ {
go func() {
a1, err := net.ResolveTCPAddr("tcp", ":3000")
if err != nil {
panic(err)
}
c1, err := net.DialTCP("tcp", nil, a1)
if err != nil {
panic(err)
}
_, err = c1.Write([]byte(m))
if err != nil {
panic(err)
}
buf := make([]byte, 24)
n, err := c1.Read(buf)
if err != nil {
panic(err)
}
if string(buf[:n]) != "pong" {
panic(1)
}
err = c1.Close()
if err != nil {
panic(err)
}
g := atomic.AddInt64(&tcp, 1)
if g % 100 == 0 {
fmt.Println("tcp", g)
time.Sleep(time.Millisecond * 1000)
}
}()
go func() {
a2, err := net.ResolveUDPAddr("udp", ":3000")
if err != nil {
panic(err)
}
c2, err := net.DialUDP("udp", nil, a2)
if err != nil {
panic(err)
}
_, err = c2.Write([]byte(m))
if err != nil {
panic(err)
}
buf := make([]byte, 24)
n, err := c2.Read(buf)
if err != nil {
panic(err)
}
if string(buf[:n]) != "pong" {
panic(1)
}
err = c2.Close()
if err != nil {
panic(err)
}
g := atomic.AddInt64(&udp, 1)
if g % 100 == 0 {
fmt.Println("udp", g)
time.Sleep(time.Millisecond * 1000)
}
}()
}
signals := make(chan os.Signal, 1)
signal.Notify(signals, os.Interrupt, syscall.SIGTERM)
<-signals
}
and get a strange behavior: not all udp requests are sent or handled on many connections.
When i sent 100 or 200 both server and client tells me that all requests worked but from 1000 there is a strange ~5% requests loss on udp for both server and client but no panic.
I know udp allows packet loss but 5% on localhost requests seems like an error.
As we know, the UDP is connectionless, so packet loss may be caused by this nature of UDP. There could be several ways to lower the rate of packet loss.
Slow down the rate of packets sent on the client side
Call SetWriteBuffer to increase the buffer size on the client side and set SetReadBuffer to increase the buffer size on the server side
conn, err := net.DialUDP("udp", nil, addr)
err = conn.SetWriteBuffer(64 * 1024 * 1024)
Check the system network information through netstat -s -udp and get UDP statistics information. You could try to change the default value of rmem_max and rmem_default on the server side. For more details, please refer to 1 and 2

Can we send request form server to client and get response through quic/http3?

I'm using quic-go to implement my thought, I need the server to forwardly send request to client to get response, just like we do that client sends request to web server commonly. But with quic-go, after connection is setup, can server initialize streams to send request to client and get responses? I did a trying but haven't made it work. The code below is from the echo.go of example dir, the two parts between comment lines are added by me.
package main
import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/pem"
"fmt"
"io"
"log"
"math/big"
"github.com/lucas-clemente/quic-go"
)
const addr = "localhost:4242"
const message = "foobar"
// We start a server echoing data on the first stream the client opens,
// then connect with a client, send the message, and wait for its receipt.
func main() {
go func() { log.Fatal(echoServer()) }()
err := clientMain()
if err != nil {
panic(err)
}
}
// Start a server that echos all data on the first stream opened by the client
func echoServer() error {
listener, err := quic.ListenAddr(addr, generateTLSConfig(), nil)
if err != nil {
return err
}
conn, err := listener.Accept(context.Background())
if err != nil {
return err
}
stream, err := conn.AcceptStream(context.Background())
if err != nil {
panic(err)
}
// Echo through the loggingWriter
_, err = io.Copy(loggingWriter{stream}, stream)
if err != nil {
panic(err)
}
//------------------------------
stream1, err := conn.OpenStream()
if err != nil {
panic(err)
}
message := "aaaaa"
fmt.Printf("2-Server: Sending '%s'\n", message)
_, err = stream1.Write([]byte(message))
//------------------------------
return err
}
func clientMain() error {
tlsConf := &tls.Config{
InsecureSkipVerify: true,
NextProtos: []string{"quic-echo-example"},
}
conn, err := quic.DialAddr(addr, tlsConf, nil)
if err != nil {
return err
}
stream, err := conn.OpenStreamSync(context.Background())
if err != nil {
return err
}
fmt.Printf("Client: Sending '%s'\n", message)
_, err = stream.Write([]byte(message))
if err != nil {
return err
}
buf := make([]byte, len(message))
_, err = io.ReadFull(stream, buf)
if err != nil {
return err
}
fmt.Printf("Client: Got '%s'\n", buf)
err = stream.Close()
if err != nil {
return err
}
//-------------------------------
for {
stream1, err := conn.AcceptStream(context.Background())
if err != nil {
panic(err)
}
buf1 := make([]byte, len(message))
_, err = io.ReadFull(stream1, buf1)
if err != nil {
panic(err)
}
fmt.Printf("2-Client: Got '%s'\n", buf1)
err = stream1.Close()
if err != nil {
panic(err)
}
}
//-------------------------------
return nil
}
// A wrapper for io.Writer that also logs the message.
type loggingWriter struct{ io.Writer }
func (w loggingWriter) Write(b []byte) (int, error) {
fmt.Printf("Server: Got '%s'\n", string(b))
return w.Writer.Write(b)
}
// Setup a bare-bones TLS config for the server
func generateTLSConfig() *tls.Config {
key, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
panic(err)
}
template := x509.Certificate{SerialNumber: big.NewInt(1)}
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
if err != nil {
panic(err)
}
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
if err != nil {
panic(err)
}
return &tls.Config{
Certificates: []tls.Certificate{tlsCert},
NextProtos: []string{"quic-echo-example"},
}
}
You are close.
Notice how the server writes, then returns, it reaches out to log.Fatal before the client had a chance to read and handle the data.
Take care to the message variable, one is 6 length long, the other one is only 5 length long.
Properly close your stream, the server was not ending it ending before handing over;
package main
import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/pem"
"fmt"
"io"
"log"
"math/big"
"github.com/lucas-clemente/quic-go"
)
const addr = "localhost:4242"
const message = "foobar"
// We start a server echoing data on the first stream the client opens,
// then connect with a client, send the message, and wait for its receipt.
func main() {
go func() {
err := echoServer()
if err != nil {
log.Println(err)
}
}()
err := clientMain()
if err != nil {
panic(err)
}
}
// Start a server that echos all data on the first stream opened by the client
func echoServer() error {
listener, err := quic.ListenAddr(addr, generateTLSConfig(), nil)
if err != nil {
return err
}
conn, err := listener.Accept(context.Background())
if err != nil {
return err
}
stream, err := conn.AcceptStream(context.Background())
if err != nil {
panic(err)
}
// Echo through the loggingWriter
_, err = io.Copy(loggingWriter{stream}, stream)
if err != nil {
log.Println(err)
return err
}
//------------------------------
fmt.Printf("Server: open stream\n")
stream1, err := conn.OpenStream()
if err != nil {
return err
}
fmt.Printf("2-Server: Sending '%s'\n", message)
var n int
n, err = stream1.Write([]byte(message))
fmt.Printf("Server: write %v %v\n", n, err)
stream1.Close()
//------------------------------
return err
}
func clientMain() error {
tlsConf := &tls.Config{
InsecureSkipVerify: true,
NextProtos: []string{"quic-echo-example"},
}
conn, err := quic.DialAddr(addr, tlsConf, nil)
if err != nil {
return err
}
stream, err := conn.OpenStreamSync(context.Background())
if err != nil {
return err
}
fmt.Printf("Client: Sending '%s'\n", message)
_, err = stream.Write([]byte(message))
if err != nil {
return err
}
buf := make([]byte, len(message))
_, err = io.ReadFull(stream, buf)
if err != nil {
return err
}
fmt.Printf("Client: Got '%s'\n", buf)
err = stream.Close()
if err != nil {
return err
}
//-------------------------------
for {
fmt.Printf("Client: accept stream\n")
stream1, err := conn.AcceptStream(context.Background())
if err != nil {
return err
}
fmt.Printf("Client: got stream %v\n", err)
buf1 := make([]byte, len(message))
_, err = io.ReadFull(stream1, buf1)
if err != nil {
return err
}
fmt.Printf("2-Client: Got '%s'\n", buf1)
err = stream1.Close()
if err != nil {
return err
}
break
}
//-------------------------------
return nil
}
// A wrapper for io.Writer that also logs the message.
type loggingWriter struct{ io.Writer }
func (w loggingWriter) Write(b []byte) (int, error) {
fmt.Printf("Server: Got '%s'\n", string(b))
return w.Writer.Write(b)
}
// Setup a bare-bones TLS config for the server
func generateTLSConfig() *tls.Config {
key, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil {
panic(err)
}
template := x509.Certificate{SerialNumber: big.NewInt(1)}
certDER, err := x509.CreateCertificate(rand.Reader, &template, &template, &key.PublicKey, key)
if err != nil {
panic(err)
}
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: certDER})
tlsCert, err := tls.X509KeyPair(certPEM, keyPEM)
if err != nil {
panic(err)
}
return &tls.Config{
Certificates: []tls.Certificate{tlsCert},
NextProtos: []string{"quic-echo-example"},
}
}

How do I make it such that a TCP connection will timeout if the connection doesn't receive a response every second?

I'm trying to create a TCP server that will timeout if the client does not respond within the span of every second.
I tried:
func main() {
listener, err := net.Listen("tcp", "localhost:8000")
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.Accept()
conn.SetDeadline(time.Now().Add(timeout))
if err != nil {
log.Print(err)
}
go handleConn(conn)
}
}
where the timeout is a single second but the disconnects immediately, not even waiting for a reply.
What you want can be achieved by setting socket options on your listener. Tweak the values as per your needs
Note that this is its own KeepAlive and does not depend on incoming/outgoing data by application
func enableTCPKeepAlive(listener *net.TCPListener) error {
rawConn, err := listener.SyscallConn()
if err != nil {
return err
}
cfg := config.TLSServerConfig()
rawConn.Control(
func(fdPtr uintptr) {
// got socket file descriptor. Setting parameters.
fd := int(fdPtr)
//Idle time before sending probe.
err = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, cfg.TCPKAIdleTime)
if err != nil {
return err
}
//Number of probes.
err := syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPCNT, cfg.TCPKANumProbes)
if err != nil {
return err
}
//Wait time after an unsuccessful probe.
err = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, cfg.TCPKAInterval)
if err != nil {
return err
}
// go syscall doesn't have the constant 0x12 (18) for TCP_USER_TIMEOUT.
// 0x12 value referenced from linux kernel source code header:
// include/uapi/linux/tcp.h
err = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, 0x12, cfg.TCPKAUserTimeout)
if err != nil {
return err
}
})
return nil
}
There are more options available than the ones I have mentioned above.
Call this function on your listener before the for loop.
func main() {
listener, err := net.Listen("tcp", "localhost:8000")
if err != nil {
log.Fatal(err)
}
err = enableTCPKeepAlive(listener)
if err != nil {
log.Fatal(err)
}
for {
conn, err := listener.Accept()
conn.SetDeadline(time.Now().Add(timeout))
if err != nil {
log.Print(err)
}
go handleConn(conn)
}
}
The problem is almost always in code that is not posted here. The function obviously works like a charme:
package main
import (
"crypto/rand"
"log"
"net"
"time"
)
func main() {
listener, err := net.Listen("tcp", "localhost:8000")
if err != nil {
log.Fatal(err)
}
go func() {
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
return
}
go func(c net.Conn) {
defer c.Close()
conn.SetDeadline(time.Now().Add(2 * time.Second))
if err != nil {
log.Print(err)
return
}
buf := make([]byte, 1<<19) // 512 KB
for {
_, err := conn.Read(buf)
if err != nil {
log.Print(err)
break
}
}
}(conn)
}
}()
payload := make([]byte, 1<<20)
_, err = rand.Read(payload) // generate a random payload
if err != nil {
log.Print(err)
}
conn, err := net.Dial("tcp", listener.Addr().String())
if err != nil {
log.Fatal(err)
}
log.Println("Connected to server.")
time.Sleep(5 * time.Second)
_, err = conn.Write(payload)
if err != nil {
log.Print(err)
}
listener.Close()
}

Golang TCPConn Gob Communication

I'm having issues with the gob protocol (or maybe networking in general, where my knowledge is weak), and I don't understand why the following code does not work properly. It is just supposed to be a simple example of maintaining an open TCP connection, and sending multiple gobs through it. The code will send, and receive, but often corrupts its data.
Thank you in advance.
package main
import (
"encoding/gob"
"fmt"
"net"
"strconv"
"time"
)
type Message struct {
Msg string
}
func main() {
gob.Register(new(Message))
clientAddr, err := net.ResolveTCPAddr("tcp", "localhost:12346")
if err != nil {
fmt.Println(err)
}
serverAddr, err := net.ResolveTCPAddr("tcp", "localhost:12345")
if err != nil {
fmt.Println(err)
}
serverListener, err := net.ListenTCP("tcp", serverAddr)
if err != nil {
fmt.Println(err)
}
conn, err := net.DialTCP("tcp", clientAddr, serverAddr)
if err != nil {
fmt.Println(err)
}
serverConn, err := serverListener.AcceptTCP()
if err != nil {
fmt.Println(err)
}
done := false
go func() {
for !done {
recieveMessage(serverConn)
}
}()
for i := 1; i < 1000; i++ {
sent := Message{strconv.Itoa(i)}
sendMessage(sent, conn)
}
time.Sleep(time.Second)
done = true
}
func sendMessage(msg Message, conn *net.TCPConn) {
enc := gob.NewEncoder(conn)
err := enc.Encode(msg)
if err != nil {
fmt.Println(err)
}
}
func recieveMessage(conn *net.TCPConn) {
msg := new(Message)
dec := gob.NewDecoder(conn) // Will read from network.
err := dec.Decode(msg)
if err != nil {
fmt.Println(err)
}
fmt.Println("Client recieved:", msg.Msg)
}
The problem is that the decoder can buffer data from the next message. When this happens, the next new decoder starts in the middle of a message. The fix is to use a single encoder and decoder.
func main() {
...
dec := gob.NewDecoder(conn) // Will read from network.
enc := gob.NewEncoder(serverConn)
go func() {
for !done {
recieveMessage(dec)
}
}()
for i := 1; i < 1000; i++ {
sent := Message{strconv.Itoa(i)}
sendMessage(sent, enc)
}
...
}
func sendMessage(msg Message, enc *gob.Encoder) {
err := enc.Encode(msg)
if err != nil {
fmt.Println(err)
}
}
func recieveMessage(dec *gob.Decoder) {
msg := new(Message)
err := dec.Decode(msg)
if err != nil {
fmt.Println(err)
}
fmt.Println("Client recieved:", msg.Msg)
}
Run it in the playground

Resources