I know my friend's external IP (from whatsmyip) and internal IP (e.g 192.168.1.x) and he knows mine. How do I establish a TCP connection with him?
Is it possible to do it without any port forwarding? Or do I require a server with an external IP to transfer messages between me and him?
Basically, it isn't (shouldn't be) possible for you to connect to your friends private IP through his firewall. That's the point of firewalls :-o
Two solutions - the simplest is a port forwarding rule on his firewall, the second is as you suggest an external server that both clients connect to.
Connecting to a known external ip and internal ip without port forwarding