To make such a plugin properly, it will probably require a client-server architecture where both sides would mutate the TLS handshake in turns to brute-force the fingerprints.
At the same time, an off-band communication channel between the client and the server might be needed so that they can signal to each other which packets get censored and what the next bisection step should be.
Some thoughts: Let's say that we have an OONI client C in <censored country> and an OONI server S anywhere else in the world. To RE the DPI fingerprint of <censored country>:
In the client-side C, OONI should fire up Tor and capture its (handshake) traffic (with libpcap).
If Tor was not blocked, we are done already.
If Tor was blocked, feed the pcap to OONI. OONI should output a tuple of messages for each side which signify the messages that each side should send or expect to receive [0].
4a. In the client-side C, sequentially do nmutated handshakes, where n is the total number of bytes of messages. [1]
4b. Foreach handshake, figure out if it was censored. If yes, the currently mutated handshake byte was not part of the DPI fingerprint. If it was censored, we found a byte of the fingerprint and we add it to our list. [2]
Output the list of fingerprints.
By mutated handshake we mean a full TLS handshake where one of its bytes will be mutated (increased by one).
By figure out if it was censored we mean detecting a network behavior that signifies that a handshake was blocked. That might be absense of ACK, a TCP RST, a TCP retransmission, etc. The figure out part is not that easy since each DPI box might have different ways of blocking (for example a DPI box might not block the current connection, but might block any subsequent connections).
[0]: This tuple might look like this (example for the client-side):
(, , <ClientKeyExchange, ChangeCipherSpec, ClientHelloDone data>, ...)
[1]: What happens if the block is permanent? Do we have to use a different bridge IP or TCP port for each mutation?
[2]: What happens if the handshake triggers active probing instead of instant blocking? Do we need n different bridge IPs (or TCP ports)?