Finally cracked this, thanks to some help from @SynchroM on a mailinglist. He pointed me at the testssl.sh tool and suggested that I add TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 to my nginx ssl_ciphers line.
I did this, but testssl.sh -e beyourself.crohnsandcolitis.org.uk was still showing none of those ciphers, even after an nginx restart.
Then I changed the ssl_ciphers to only include those ciphers, but nginx -t then reported an error:
ginx: [emerg] SSL_CTX_set_cipher_list("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256") failed (SSL: error:1410D0B9:SSL routines:SSL_CTX_set_cipher_list:no cipher match)
nginx: configuration file /etc/nginx/nginx.conf test failed
which clued me in to the fact that you need to look at nginx and openssl. Running openssl ciphers -v showed neither of those two ciphers, so I needed to pick ciphers that the Java client understood and that my install of openssl supported.
Again, @SynchroM to the rescue, he pointed me at https://www.ssllabs.com/ssltest/viewClient.html?name=Java&version=8u31&key=86 which lists the Java client’s ciphers, and https://testssl.sh/openssl-rfc.mapping.html which maps them to openssl.
Open SSL Cipher Suite
--------------------------------------------------------------------
AES128-SHA TLS_RSA_WITH_AES_128_CBC_SHA
DHE-DSS-AES128-SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA
DHE-RSA-AES128-SHA TLS_DHE_RSA_WITH_AES_128_CBC_SHA
AES128-SHA256 TLS_RSA_WITH_AES_128_CBC_SHA256
DHE-DSS-AES128-SHA256 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
DHE-RSA-AES128-SHA256 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
AES128-GCM-SHA256 TLS_RSA_WITH_AES_128_GCM_SHA256
DHE-RSA-AES128-GCM-SHA256 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
DHE-DSS-AES128-GCM-SHA256 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
ECDH-ECDSA-AES128-SHA TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
ECDHE-ECDSA-AES128-SHA TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
ECDH-RSA-AES128-SHA TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
ECDHE-RSA-AES128-SHA TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
ECDHE-ECDSA-AES128-SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
ECDH-ECDSA-AES128-SHA256 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
ECDHE-RSA-AES128-SHA256 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
ECDH-RSA-AES128-SHA256 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
ECDHE-ECDSA-AES128-GCM-SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
ECDH-ECDSA-AES128-GCM-SHA256 TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
ECDHE-RSA-AES128-GCM-SHA256 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
ECDH-RSA-AES128-GCM-SHA256 TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
I ended up adding all of them…
AES128-SHA:DHE-DSS-AES128-SHA:DHE-RSA-AES128-SHA:AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES128-SHA256:AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDH-ECDSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDH-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDH-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDH-RSA-AES128-GCM-SHA256
to my ssl_ciphers line:
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:AES128-SHA:DHE-DSS-AES128-SHA:DHE-RSA-AES128-SHA:AES128-SHA256:DHE-DSS-AES128-SHA256:DHE-RSA-AES128-SHA256:AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:ECDH-ECDSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDH-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA256:ECDH-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDH-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDH-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDH-RSA-AES128-GCM-SHA256;
and finally! The Twitter card validator can handshake.