In my team it works like this:
When we are facing a problem, something bad has happened, the project is on fire - we usually have contact with the client on Management Level (either PM or TeamLead). The same applies when the client asks how much/long would it take to add a feature X. In such cases developers are told to forward the conversation to Management Level. Client have people on Management Level on his side too.
Then, if developers are working on a specific feature, or there is a bug submitted from a specific user at client side, developers are obliged to contact the person directly.
We came to this approach from trying more restrictive ones:
- Single Point of Contact - we had problems with distortions of the messages passeed: from the client to the SPoC person, than to developers, and than back the same way
- Everybody - we had problems that some things were consulted with developers excluding Management Level; another problem was, that developers were directly blamed about something by client
Now we succesfully work with our model for about a year. Developers have less distractions from clients, and on the other side they get specific information on low-level tasks directly from the person interested in it.