Can't build TCP connection with peers to send handshake message in golang, Bittorrent client - go

I am trying to build a bittorrent client. I wrote this function to verify that I can establish connection to send messages to other peers but its not working.
func handShake(torrent *gotorrentparser.Torrent, peer Peer, peedId []byte) {
conn,err := net.Dial("tcp", peer.ip + ":" + strconv.Itoa(int(peer.port)))
if err != nil {
panic(err)
}
defer conn.Close()
}
Here peer is a struct of string ip and uint16 port.
Getting the following error:
panic: dial tcp 152.57.73.47:27569: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
Couldn't find any similar issues. I tried to fix my local port address to be same as what I used to send the announce request but that didn't work either.
Edit: I tried with a different torrent, it is failing for some peers, but now it is working for some other peers. Is the issue only when the peer is using utorrent as bittorrent clients?

If you're developing a bittorrent client you should start with a more reproducable setup such as running an existing client with a known infohash on your local machine and then connecting to that (without using a tracker). Once you got that to work you can work on a tracker client implementation and then put those pieces together.
The internet is unreliable and bittorrent consists of many moving parts, so a single connection failure won't tell you much, you'll have to ensure that each part works properly and try with torrents that you have tested in an existing client to narrow down the cause of problems.

After few days here is the problem that I found.
Not all peers are able to accept an inbound request as they are behind a NAT.
Even when I hosted a torrent from one of my computer and tried to download through another system, I couldn't download as there was no reply from the peer for the SYN message being sent.
I was only able to download, when both the clients were on the same network and local peer discovery was enabled, and the TCP connection was also build with the local IP address.

Related

Check for server reachability in Golang conn.Write

I am working on an application that tries to send some data to a remote server. Once I get the hostname, I get a connection by resolving the hostname using net.Dialer.DialContext. Once, I resolve the hostname, I keep on using conn.Write method to write data to the connection.
conn, err := d.DialContext(ctx, string(transport), addr)
_, err := client.conn.Write([]byte(msg))
Error faced: I observed that due to some issues, I was not able to ping my server. Surprisingly, conn obtained from DialContext did not complain while doing conn.Write and it kept writing to the same connection.
Can someone help me in how to modify my writing methods in order to get an error in case the destination server is not reachable?
From this UDP connection example
the best a "connected" UDP socket can do to simulate a send failure is to save the ICMP response, and return it as an error on the next write.
So try and (for testing) make a second conn.Write, to confirm that you would indeed get an error this time.

TLS handshake error from xx.xx.xx.xx:14333: EOF

I am running a HTTPS server in Linux (RHEL 7). I am getting the below error as soon as I start the server.
2019/09/04 15:46:16 http: TLS handshake error from xx.xx.xx.xx:60206: EOF
2019/09/04 15:46:21 http: TLS handshake error from xx.xx.xx.xx:31824: EOF
This error is coming automatically and continuously in the terminal.
Below is the go code for creating https server -
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
fmt.Println("Starting webserver")
router := gin.Default()
router.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"success": true,
})
})
router.RunTLS(":9001", "server.pem", "server.key")
}
We have purchased and combined the server certificate, intermidate certificate and root certificate into a single file to make the server.pem file.
As this error is coming continuously and in the terminal as soon as I start the server, I think there is some configuration problem in the VM?
Please suggest what are the things I can check here.
NOTE: This error is specific to the Go. I have tested on the same server on the same port with same certificates in Node JS. And it works fine.
Also the IP in the error message is of the reverse proxy server (WAF) which is continuosly doing health monitoring of the web application server.
I would attack the problem from two angles:
What is this xx.xx.xx.xx address? I'd expect that when I start some random piece of software, there is nothing to connect to it all by itself, right?
Is there anything special about that 9001 port? Try running nc -l -p 9001 and see whether those unidentified connections happen as well.
Run tcpdump and see whether there is any incoming traffic from the clients making those connections: those EOFs (that's "end of file") reported by the TLS mchinery most probably mean those clients—whatever they are—close their side of the connection somewhere amidst the TLS handshake—while the server is expecting to read some data from them.
This hints at that those clients do not actually expect to see TLS protocol in the connection they open; and they pretty much may send some plaintext in it, so you'll be able to peek at it.
Googling for "9001 port" hints at that it's used for some "ETL service manager" protocol—whatever it is. This hints at that traffic on 9001 might be related to VoIP.
I have no idea what to do with this, but it might give you some lead for further research.

Problem with gRPC setup. Getting an intermittent RPC unavailable error

I have a grpc server and client that works as expected most of the time, but do get a "transport is closing" error occasionally:
rpc error: code = Unavailable desc = transport is closing
I'm wondering if it's a problem with my setup. The client is pretty basic
connection, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
pb.NewAppClient(connection)
defer connection.Close()
and calls are made with a timeout like
ctx, cancel := context.WithTimeout(ctx, 300*time.Millisecond)
defer cancel()
client.MyGRPCMethod(ctx, params)
One other thing I'm doing is checking the connection to see if it's either open, idle or connecting, and reusing the connection if so. Otherwise, redialing.
Nothing special configuration is happening with the server
grpc.NewServer()
Are there any common mistakes setting up a grpc client/server that I might be making?
After much search, I have finally come to an acceptable and logical solution to this problem.
The root-cause is this: The underlying TCP connection is closed abruptly, but neither the gRPC Client nor Server are 'notified' of this event.
The challenge is at multiple levels:
Kernel's management of TCP sockets
Any intermediary load-balancers/reverse-proxies (by Cloud Providers or otherwise) and how they manage TCP sockets
Your application layer itself and it's networking requirements - whether it can reuse the same connection for future requests not
My solution turned out to be fairly simple:
server = grpc.NewServer(
grpc.KeepaliveParams(keepalive.ServerParameters{
MaxConnectionIdle: 5 * time.Minute, // <--- This fixes it!
}),
)
This ensures that the gRPC server closes the underlying TCP socket gracefully itself before any abrupt kills from the kernel or intermediary servers (AWS and Google Cloud Load Balancers both have larger timeouts than 5 minutes).
The added bonus you will find here is also that any places where you're using multiple connections, any leaks introduced by clients that forget to Close the connection will also not affect your server.
My $0.02: Don't blindly trust any organisation's (even Google's) ability to design and maintain API. This is a classic case of defaults-gone-wrong.
One other thing I'm doing is checking the connection to see if it's either open, idle or connecting, and reusing the connection if so. Otherwise, redialing.
grpc will manage your connections for you, reconnecting when needed, so you should never need to monitor it after creating it unless you have very specific needs.
"transport is closing" has many different reasons for happening; please see the relevant question in our FAQ and let us know if you still have questions: https://github.com/grpc/grpc-go#the-rpc-failed-with-error-code--unavailable-desc--transport-is-closing
I had about the same issue earlier this year . After about 15 minuets I had servers close the connection.
My solution which is working was to create my connection with grpc.Dial once on my main function then create the pb.NewAppClient(connection) on each request. Since the connection was already created latency wasn't an issue. After the request was done I closed the client.

Connectex: Error connecting to a physical device

I am trying to communicate with a device (connected using ethernet) using TCP/IP connection. When a connection request is sent, I am getting an error:
dial tcp 192.168.137.10:502: connectex: A connection attempt failed because
the connected party did not properly respond after a period of time,
or established connection failed because connected host has failed to respond
But if I am connecting to the simulator (which will act as device), it is getting connected and sending me response.
I am using GO for coding. This is my code to connect to device
conn, err := net.Dial("tcp", "192.168.137.10:502")
if err != nil {
return nil, err
} else {
return conn, nil
}
Hardware Info:
Windows 10, 64 bit machine
PLC device connected over TCP/IP
I suspect that there is a problem with the server and not your client code. The fact that you aren't just getting a "connection refused" error tells me that the remote port is probably open. Chances are that the server is not performing an accept() on the incoming connection within a reasonable time.
Things that might cause this
Maximum number of connection configured on the server has been exceeded or the service is too busy.
Server has crashed
Funny firewall or another routing issue between you and the server. Some deep packet inspection firewalls sometimes cause these types of issues.
I suggest you try and do troubleshooting on the server side.

Unable to make a UDP request

I am trying to build a BitTorrent client in go. I need to make UDP requests to connect to the various trackers. For this I use the net package and do this:
net.Dial("udp", "udp://hostname:1337/announce")
I get a "too many colons in address" error.
If I try this:
net.Dial("udp", "hostname:1337/announce")
I get a "nodename nor servname provided, or not known" error.
How do I fix this?
So you'll need to send it to the IP address and port as provided by the .torrent metafile (announce field).
And once you open the net.Conn you can conn.Write() to the socket and similarly conn.Read()
So you've just about gotten i:
conn, err := net.Dial("udp", announceAddr:Port)
When connecting with HTTP, yeah you use the /announce endpoint, but not with UDP
The specs explain how many bytes to read and write (it is fixed at first, but later dynamic when it comes to reading the peer list). I've found this link, rather, the most useful: https://github.com/naim94a/udpt/wiki/The-BitTorrent-UDP-tracker-protocol

Resources