> But what prevents one peer from > impersonating another? Absolutely nothing, because by the time the > message gets to the application layer the authentication information > has been lost.
The thing that prevents one peer from impersonating another is each peer should have a unique secret shared only with the server. Any other client that attempts to send a message with a bogus client id will fail because it cannot authenticate the message (HMAC, etc) because it doesn't have the key. Client C sends message M to server S with key K using MC+HMAC(MC, K) -> S. This means the client sends the message M and client identity C along with the HMAC of the message M and client C using key K to the server S. Ok so far? Now, replay attacks are another problem. Client C sends message M to server S, and jerk J sees the message on the line. If J re-sends M to S, S cannot tell that the message didn't originate from C. I think this is the problem you're trying to explain. So what is one way to solve it? Time. When client C sends a message, we add time T to the message: MCT+HMAC(MCT, K) -> S Once the server receives the message, it verifies the HMAC of MCT to authenticate the message, then verifies the time T is within +/-whatever seconds of "now". If a time stamp on a message deviates more than however many seconds/minutes/whatever from the server time, we assume the message is a replay and discard it. Another method is an integer sequence I. For every message M the client sends, it increments the counter. I++, then MCI+HMAC(MCI, K) -> S The server maintains a dictionary D of counters by client C. We'll call this D[C] = I When the server S receives a message M from the client C, it can check D[C] <= I to see if the last seen counter is less than or equal to the received messages' I. If so, discard the message as a replay. If not, save D[C] = I for the next time we receive a message from the client. An advantage to using time is that you don't have to hold a dictionary on the server. However if a replay could happen in sub-millisecond time, you may not be able to reliably use that method. Hope this helps. On Sat, May 11, 2013 at 2:14 PM, Randall Nortman <[email protected]>wrote: > I know this has been discussed before on this list and there are some > RFC's related to secure authentication, but I have not yet seen any > reasonable solutions, because of a limitation in the libzmq API. The > encryption/authentication built into ZMTPv3.0 doesn't seem to fix the > problem, because the problem is at the API level. Let me start by > illustrating the problem with a simple example: > > Let's say we have a server which maintains some data for > clients/peers. Let's call the data "files" for this example, but it > could be anything. The files are owned by particular clients (which > are peers with respect to the protocol, but clients with respect to > the file service). Clients are somehow known to the server > (previously shared keys), and they can store and retrieve their own > files, but should not be able to access the files of other clients. > > Let's say you do something smart like put the whole thing on a VPN > using client certificates to authenticate clients and assign them a > static IP on the VPN. The VPN makes sure that the private IP > addresses cannot be spoofed. So if I were writing a server based on > traditional sockets rather than ZMQ, I'd just trust that if I get a > packet from 10.0.0.96, then that is definitely from the client > assigned that address and no additional authentication is required. > You could also do it with SSL using client certificates, and then my > SSL-based server would just query the SSL library for the identity of > the client connected to the socket and everything would be great. > > Now let's say you've got ZMQ running on top of the same kind of VPN or > SSL setup. Or you're using the CurveCP/CurveZMQ underlying transport > or the SASL mechanism in the ZMTPv3.0 spec. Great, you at least know > that anybody that connects to you is a known peer. But when you get a > message, you don't know what peer sent it, because zmq_recv has no way > of communicating that to you. So your protocol of course will need to > have the client ID in each message. But what prevents one peer from > impersonating another? Absolutely nothing, because by the time the > message gets to the application layer the authentication information > has been lost. > > So now you *have* to put authentication on top of ZMQ, at the > application level, and sign each message. So now each ZMQ application > needs to implement crypto, and it is way, way too easy to get that > wrong to have it happening at the application layer. (The > pubsub-security draft at http://www.zeromq.org/topics:pubsub-security > nicely illustrates how easy it is to get this stuff terribly, horribly > wrong, because nothing in that protocol stops replay attacks, as has > already been pointed out in the comments.) > > Furthermore, it seems like unnecessary overhead, given that the > underlying layers may already have authenticated the peer (if auth at > the ZMTP layer is being used, for example, or CurveCP/TLS/VPN > underneath that). > > Could the API simply provide a way to identify the sender of each > message somehow? The "identity" could be handled as a blob whose > interpretation is dependent on the underlying transport, anything from > an IP address up to the CN from the peer's X509 certificate. This > does not do a whole lot to help in the case of multi-hop > (routed/proxied) messages, but it at least gives you single-hop > authentication, which is good enough for a large number of > applications. And it could perhaps serve as the basis for end-to-end > multi-hop authentication as well. If end-to-end auth is going to be > done by signing each message (a reasonable way to do it), then that > *must* be part of the ZMQ spec and the libzmq implementation, because > you simply cannot leave it up to each application to design and > implement crypto properly. > > Am I missing something? Has this been handled somehow already? > _______________________________________________ > zeromq-dev mailing list > [email protected] > http://lists.zeromq.org/mailman/listinfo/zeromq-dev >
_______________________________________________ zeromq-dev mailing list [email protected] http://lists.zeromq.org/mailman/listinfo/zeromq-dev
