How to determine custom synchronization status?
Bitcoin Core 0.10.0 may provide the solution you need thanks to its headers-first synchronization.  The getblockchaininfo RPC in 0.10.0 provides both a blocks field (the number of verified blocks) and a headers field (the number of partially-validated headers).

Any time the numbers differ, you don't have all the blocks.  During Initial Block Download (IBD), they'll be hundreds of thousands of blocks apart.  (According to a Wireshark sniff I did during IBD a few weeks ago, it took my node less than two minutes to download a complete headers chain; syncing the blocks then took another three hours.)

Bitcoin Core 0.10.0 has two other new fields you might find useful, both in the getpeerinfo RPC.  The fields are synced_headers and synced_blocks.  The headers field is based on the last P2P headers message the remote node sent you.  The blocks field is based on the last P2P block inv message the peer sent you.  In both cases, they let you know the last header or block you have in common with the remote node (as best as can be determined).

I don't know how useful these getpeerinfo fields will be, as your node can't tell you the height of a block until it has the corresponding block header---at which point the getblockchaininfo RPC will already tell you that you're out of sync.  However, they are kinda fun to look at.




  Could I just make multiple getheaders requests and see if the peer returns any headers later than the header I have, or would the peer ban me for requesting the same headers again and again?


As far as I know, there's no ban score there (as long as your packets are valid).  However, the remote peer should send you an inv message as soon as it validates an incoming block---so there's no need to poll it as long as your app handles inv messages with a MSG_BLOCK type.