If you pass a specific IP to the interface keyword argument instead of "::", the UDP port will bind to that specific IP and will only send datagrams on that IP. You can use netifaces package (e.g. find it on PyPI) to list all local IPs. So you could do the equivalent of "::" by binding multiple times, once for each IPv6 address.

Thanks for the hint - I've ran a few tests with netifaces. Few observations:
1. Returned interface identifiers for Windows are not human-readable - it's hard to determine which interface is wireless, and which one is loopback from just the interface identifier. Results for Linux are better - identifiers are human readable (eth0, wlan0, lo, etc.) - it might be possible to implement some simple logic to automatically choose the right interface.
2. As far as I noticed it is not possible to use one DatagramProtocol instance to listen on multiple addresses, so I think to achieve "::" equivalent I have to use separate DatagramProtocol instance for each address. However I think in many cases it's enough to deploy server on a single address, provided it's a reachable and well-known one.
3. I've checked some docs and see no easy way to deploy a server which automatically listens on all interfaces and responds with a source address that was used in request . It seems that it has nothing to do with Twisted. It is rather caused by the underlying Python socket implementation.

All in all the problem with using wrong source address can be easilly solved with a bit of user attention, however it's hard to find the solution that "just works".

Best Regards