Heyo!
I am writing an application in Qt/C++ that creates connections between peers. The first step in my protocol is for a new peer to broadcast it's information, soliciting connections from established peers. The location of these peers is unknown.
To do this I am using a UDP Broadcast. Since this broadcast contains information about the peer, I would like it to be encrypted. However, peer authentication happens when a TCP connection is established between peers, so there is still plenty of security beyond the UDP broadcast, but I just don't want to be too easily intercepted and interpreted by a 3rd party.
What I am looking for is a simple way to encrypt the datagram.
Can anyone suggest a reliable method?
Thanks a million!
You can use pretty much any encryption method you want what is more important/difficult is key distribution.
E.G. if all the clients just use the same symmetric encryption method like AES then the broadcast information will be encrypted but anyone who decompiles your client may be able to find out the key.
Have a look at :
How to encrypt and decrypt a file with Qt/C++?
When broadcasting a message to unknown hosts, you will be giving up your IP address and port number. You would have to have a pre-shared key for a broadcast to be meaningful, and as "brain" pointed out, that limits your ability to be secure. If you are feeling sufficiently secure with all clients being able to decrypt as well as anybody who reverses it, then you'll be ok. You can use any symmetric form of encryption and be relatively safe. For the very simplistic, XORing the data could be sufficient in this case.
If you want to be more secure in your broadcast, make your broadcast message a Diffie-Hellman key exchange message. The rest of the exchange after that can be unicast and use different numbers for each client. This would permit a new key for every individual connection. Granted somebody could re-implement your protocols and fake being a peer, but they wouldn't be able to get information from any other peers.
Related
I am trying to write a simple client-server application where a client can send or broadcast a message to one or all clients in the network. The server stores all IP addresses that are connected to it, and broadcasts a new IP if a new client connects itself.
I'm not quite sure how to implement the sending of a single message to another client. Would I just have to send a TCP message to the server and put the desired recipient as data in the TCP layer which is then extracted by the server so it knows where to send it?
I also want to add encryption to the messages which would then no longer allow the server to read the data, so I'm not sure how to solve that!?
I am using c++ and Qt5 for the implementation
I'm not quite sure how to implement the sending of a single message to
another client. Would I just have to send a TCP message to the server
and put the desired recipient as data in the TCP layer which is then
extracted by the server so it knows where to send it?
In an ideal world, the clients could talk to each other directly, since they could find out the IP addresses of the other clients from the server (either via its broadcast or by requesting a list of IP addresses from the server). If all of your clients are running on the same LAN, that can work well.
Assuming you want your system to run on the general Internet, however, that won't work so well, since many/most clients will be behind various firewalls and so they won't accept incoming TCP connections. (There are some ways around that, but they require a very advanced understanding of how TCP works, and even then they only work in certain situations, so I don't recommend attempting them in a first project)
Therefore, for a reliable client->client messaging mechanism, your best bet is indeed to have the sending client send the message to the server, along with some short header that tells the server which other client(s) the message ought to be forwarded to. My own client/server messaging system works along these lines, and I've found it to work well.
I also want to add encryption to the messages which would then no
longer allow the server to read the data, so I'm not sure how to solve
that!?
Don't worry about adding encryption until you've got the basic non-encrypted functionality working first, since encryption will make things much more difficult to debug. That said, it's perfectly possible to pass encrypted/opaque data to the server, as long as the aforementioned header data (which tells the server where to forward the message to) is not encrypted (since the server will need to be able to read the header to know what to do with the encrypted data). The trickier part will be when the receiving client gets the forwarded data from the server -- how will the receiving client know how to decrypt it? You'll need some external mechanism for clients to share keys (either symmetric keys or public/private keypairs), since if you sent the encryption keys themselves through the server, there wouldn't be much point in encrypting anything (since the server could retain a copy of any keys it forwarded, and use them to decrypt, if it wanted to)
I have a C++ app that connects to a nodeJS server through a TCP socket.
On socket 'handshake' the client authenticates itself with a UUID known by the server, the server then associates the account to this recognised UUID
Once a TCP socket is open, the app sends requests and the server answers through the same socket.
Is it necessary to add passphrase to every request to be sure the request comes from the client? Or is a socket supposed to be in place and remain in place?
So should I be sure the client is the client:
Only when opening the socket?
Every time a request is made?
The UUID known to the server is normally called a token. And it can be used for your scenario. However it should never be done unencrypted.
What you need to make sure is the following:
An external party (not one of the 2 members of the communication) should not be able to read the token.
The client should not connect to anything but YOUR server.
This is typically accomplished using TLS. (This is what makes HTTPS secure.)
I suggest you do some research into token-based authentication/authorization and TLS/SSL.
One last advice: do not implement the encryption code yourself but use a well used library that has as a result had a lot of testing and has good maintenance.
No, it's not "secure". Your scheme is susceptible to, just off the top of my head, replay attacks, man-in-the-middle attacks, eavesdropping, subsequent impersonation ...
A socket isn't like an actual physical pipe or tunnel. A socket is just an agreement that data marked with a certain source and destination port pair (these are just numbers) are to be treated as belonging to a particular logical data channel. This is determined by handshake and trust. There is no verification.
What you're specifically asking is whether man-in-the-middle attacks exist. Yes, yes they do.
Will requiring a passphrase be given in each packet fix that problem? No, it won't. It will be trivial to intercept and then replay. You're just giving the man in the middle the passphrase.
This is why people use encryption and other clever security schemes. If you're concerned about message authenticity and integrity, you'll need a basic grounding in communications security principles; providing one is out of the scope of this answer.
First, I want to give thanks for that amazing lib! I love it. A client is connecting himself to a server. The server should save the IP and do stuff with it later on (I really need the IP). I found that answer: http://lists.zeromq.org/pipermail/zeromq-dev/2010-September/006381.html but I don't understand how I get the IP out of the message (a XREP)... I think I am only able to read the ID, but the IP is managed internally by 0MQ. His second solution suggests to send the IP as part of the message, but I don't understand how to get the "public"-IP. I found that post: Get TCP address information in ZeroMQ
is pass bind a service to an ephemeral port, get a full connection endpoint ("tcp://ipaddress:port")
I don't get how this works. Does he mean something like a web-service?
In my opinion, it would be best to get the IP out of 0MQ (it has the IP already). I would even adjust 0MQ for that, if somebody could point to the place where the IP is saved, couldn't find it. The socket types are not that important, at the moment. I would prefer smth REQ-REP like. Thank you!
Summary:
TL;DR answer to your question is: you can't get IP address of the peer that sent a message, using ZeroMQ API.
Explanation:
ZeroMQ does not expose peer IP address because it is irrelevant for the message based communication that ZeroMQ is designed for. When it is possible for ZeroMQ to get IP address of client that is connecting to server (in example using method described here), it is useless. For a longer explanation here is how it works inside ZeroMQ and any other server implementation.
Server side of the connection does not handle connected clients by the means of the hashtable that maps IP to client, but by keeping track of connected "sockets" (socket descriptors) - when a server accepts (using accept()) a connection, it receives from operating system socket descriptor to use to communicate with connected peer. All server has to do is keep that descriptor around to read() from and write() to that client. Another client that connects to server receives another socket descriptor.
To summarize: even if ZeroMQ would be able to provide you with IP of connected peer, you should not depend on it. ZeroMQ hides from you connection management so you can focus on messaging. Connection management includes reconnections, which may result in a change of IP without changing the actual ZeroMQ socket connected on the other side.
So here's an example of why you might want to get the ip address a message was delivered from: we have a server whose job it is to synchronize updates onto occasionally-connected clients (think mobile devices here, though this is an extreme example of a mobile deivce.)
When the mobile unit comes onto the network, it sends a list of it's firmware files to the server via a dealer-router connection. The server has a list of all applicable firmware files; if the client needs an update it will initiate an update via a separate mechanism.
Since the IPs for the devices can (and do) change, we need to know the IP address associated with the mobile device FOR THIS CONNECTION, i.e. right now.
Yes, we absolutely can have the client send it's IP address in the message, but that's a waste of another n bytes of valuable satellite air time, and while not pure evil, is sure annoying. Zmq already has this information, if it didn't have it, it wouldn't be able to generate replies. The address is in the socket data, there's no reason the message couldn't (optionally, for all you guys who use wired networks and think disconnects are the exception) include a reference to the socket structure so you can get the address out of it. Other than pedantic religiosity, which is far too common in zmq.
The way ZeroMQ is designed there's no information provided on the remote IP. As far as I know you have to manage this through your application by sending that information as a message of some sort.
The messages themselves use an IP-agnostic ID which has more to do with the instance of ZeroMQ running than any particular interface. This is because there may be more than one transport method and interface connecting the two instances.
After many headaches and people advising to stop, I finally managed to get my Server/Client App to work with this API and create the required keys, i.e. Session and Exchange.
When I send the public key to the client, it successfully imports the key and will also encrypt a message using that key, but when I pass it back to the server; it decrypts the message using the session key but the message is returned as garbage (hmm.. private key is needed!). Now this could be due to way I am passing the encrypted message back via rpc, but something tells me it is something else. Ideally what I need is a clear and plain explanation of what it is I should be doing with all these keys, because the information I am currently getting is quite confused.
Do I pass the exchange public key to the client so it can encrypt a message and return for decryption.
Or:
Should I actually be encrypting the clients session key with the servers public key and then return that? (This doesn't sound right to me, but I am all ears!!!)
Please leave out comments to move to another API, or copy pasties from MSDN (I have already read all that). I am working with the Crypto API and just need a clear explanation of what keys the server should pass to the client, and then what the client should do and pass back so I can finally move on...
Sounds like you are on the right track if you really are determined to stick with that API :)
There are two distinct families of encryption algorithms in cryptography. 1) Ones that use symmetric keys and 2) those that use asymmetric keys. Symmetric key algorithms (e.g. AES, DES...) are very fast and should be used as long as there's a safe way to make sure both client and server have the same key (i.e. session key) and no one else can gain access to that key. On the other hand, asymmetric key algorithms (e.g. RSA...), which are also known private/public key algorithms, are much more computationally expensive. They have one key which can only be used to encrypt data and a second key which can only be used to decrypt data. These algorithms, as you found out, are perfect for the initial handshake and session key exchange. The server creates public/private key pair and sends the client the public key. Anyone can intercept it, but when the client encodes the session key and sends that back, pbulic key is useless if an eavesdropper wants to find out the session key. Only the server can decode the message as it is the only entity that is holding the private key. So your initial problem was that when the message came back, instead of using the private key from the pair, you were using synchronous session key and thus were getting garbage.
Essentially you've just implemented the basic handshake that SSL does (and you could easily do with very few lines of code if using OpenSSL library).
Once the handshake is performed you now have a secure channel between the client and the server. The only problem you might have is, what if someone piggy backs on your server's IP address and starts pretending like they are the real server? Your client will think he is talking to the real server, it'll do the key exchange and will start sending secure information, but that information might all end up in malicious hands if an attacker's PC happens to be on the other end.
This is where SSL's use of certificates comes in. Certificates are another example of where public/private keys are used. A trusted authority uses private key to sign certificates hash code and anyone can verify that certificate is valid by using it's attach public key against certificates identity data. This way even if attacker takes over your server's IP address, it won't be able to spoof your server's certificate.
Hey,
I'm sending messages via TCP and UDP from clients to the server while the server written in C++. I'm wondering what would be the best, must secure way to send, for example, if I want to send login data: email, password and IP. What would be the best way to send it in a message ang read the data in the server, while this data is stored in char *.
Thanks.
This doesn't really have anything to do with C++. You are asking a generic question about information security. You want to send information via TCP or UDP that includes sensitive information (email address, password, and IP). For this you need to use cryptography.
Cryptography is a complicated area where you should not try to roll your own protocols unless you know a lot about what you are doing. Instead, you should avoid UDP (because it is VERY hard to do crypto properly over UDP) and simply use SSL over TCP.
To do this from C++ you can use the OpenSSL sockets library. Both the client and the server link with the library. If you want a little help, you can debug using sslwrap, a command-line tool that allows you to use cleartext sockets from your client & server, but have the unencrypted data wrapped inside an SSL TCP connection.
As another poster stated, don't worry about C++; use SSL or TLS. This means you will need to acquire a certificate for the server, and that will cost you between $50 and $1500 dollars if you get a commercial one, or you can make your own from a intranet certificate authority that you establish yourself.
This measure will encrypt the communication, and ensure that your client is actually "talking" to the authentic server, not an imposter. However, if you need the client to also be authenticated, then you will need a second certificate (possibly one per client machine, to be precise). If that is too heavy-weight for your client needs, then consider using HMAC to help determine an authorized client from an imposter.