Non-blocking socket programing in TCL

A simple TCL script that detects if TCP socket is open and if SSL server is there.
Uses non-blocking sockets. It was written with idea of using this on a Cisco router with EEM.

SSH over SSL

This was written mostly for fun, I had the idea to be able to slip out of any network with SSH. The approach most people usually use is to run SSH server on port 443 (HTTPS) which kind of works, but only until somebody doesn't actually check what is listening there. The other quite easy way to stop SSH from connecting outside is to check inside the packets for clear string from the server, usually you get something like that:

SSH-2.0-OpenSSH_5.6p1

and there is a similar banner from the client side.

They both stand out quite a bit and are easy to spot and/or kill, example:

ngrep -K 3 '-OpenSSH_' port not 22

or snort with flexresp can do this also in a very nice and efficient way

My idea was to first hide the SSH server and then hide the communication. This is not perfect of course any one curious enough looking at the pcaps will spot something fishy, but probably this will fly pass 99% of people - any one doing real traffic analysis ? ;)

The server (sammael) acts similar to stunnel (of course sammael does much less) - it is able to terminate SSL connections and then send unencrypted traffic to a different service. When a special pass phrase is in the first packet after SSL handshake it connects to local SSH server instead of the default which is HTTP. When you point your browser to the host on which sammael is running you will see a normal HTTPS webpage.

The client (nisroc) does most of the work, it connects (can pass through HTTP proxy, and is able to use basic authentication) to the host and port on which sammael is running using SSL, checks digest of the cert to prevent MITM and if everything is correct sends the pass phrase and verifies that the connection to the SSH server was established.

Both server and client have TCP_CORK set on the sockets, so there is a bit less packet exchange between the hosts.

SCEP decoding/debugging

If you ever need to quickly decode SCEP messages, this is the fastest way to do it, probably.
The whole command should be on one line.

> cat request.txt | perl -pe 'use MIME::Base64;s/%([0-9a-f]{2})/sprintf("%s",pack("H2",$1))/eig;$_=MIME::Base64::decode($_);' |
openssl asn1parse -inform DER
or
> cat request.txt | perl -pe 'use MIME::Base64;s/%([0-9a-f]{2})/sprintf("%s",pack("H2",$1))/eig;$_=MIME::Base64::decode($_);' |
openssl pkcs7 -inform DER -print_certs -text

in the request.txt file is the part of the message after
"GET /scep/?operation=PKIOperation&message=" and until " HTTP/1.0"

What this is doing:

s/%([0-9a-f]{2})/sprintf("%s", pack("H2",$1))/eig <- url decoding

then (obvious):

$_=MIME::Base64::decode($_) <- Base64 decoding

and then parsing the DER:

openssl asn1parse -inform DER

or decoding pkcs7 directly:

openssl pkcs7 -inform DER -print_certs -text

An example request (for tests) can be taken from here, you can see the request in both Apache logs and the packet captures. In the above example in the request.txt file we would have (this should be one line):
> cat request.txt
MIAGCSqGSIb3DQEHAqCAMIIHiAIBATEOMAwGCCqGSIb3DQIFBQAwgAYJKoZIhvcNAQcBoIAEggJTMIAGCSqGSIb3DQEHA6CAMIICPAIBADGB%2BDCB9QIBADBeMFkxCzAJBgNVBAYTAkRFMQ8wDQYDVQQKEwZCaW50ZWMxCzAJBgNVBAsTAlJEMQ0wCwYDVQQDEwRyb290MR0wGwYJKoZIhvcNAQkBFg5yb290QGxvY2FsaG9zdAIBAzANBgkqhkiG9w0BAQEFAASBgMUB2pOa6F3APPRIAQwrIXTZn0V%2FsiTC2acRGiA%2BVUsjKsn8Hu0bMNVi8QkdHsmvoHQkJAO6z0gXKWIneh1v5q9cNkdvLmO%2BKOdRktmhOkiPRHHPzYOc5WBGhGiMQyvXkNtw5cUPO9FwdBN%2Fr%2BddRN27piYpaGJd1IG%2Fb3V8ObhyMIIBOgYJKoZIhvcNAQcBMBEGBSsOAwIHBAijOtCgU455MYCCARgNN4qTEL9xkhWwgjhyDV9NThb1l1jKa%2FJHvYjqEqiiCYRD66ho%2FukebGgXoNJe3sT3AUzZv5F7yngRoyPjpB2snCDqlRyAM0SEVxyF00o1Y6fu7gcIChSv%2BPa1sd2p6%2FIbi7UUq3JZ8u%2FsS9%2FuE8izsANx1fMqUUP6GGBsqxFKutVCk7P19dK6GvA7DajWiuJVb4WmixpwrghSjuAGNPn1ZBLW7ZdU64VlPVVJ8jppg1UrhNse68FQ4cVsXiJdqYszAcLnzqFSv11%2B%2FXxIZ9NBV02DkrGnRk6IC0CsBoez7RrOtFDRRIxNdtE0ntGJis9A70yZibkr%2Fm7ncjZy6nDgpvQjaTRVtFY5s%2B51ownh1x DyGjTPl%2FzNAAAAAAAAAACgggLsMIIC6DCCAlGgAwIBAgIRAIf%2F%2BJDqYyywkpHcqS2%2BvGEwDQYJKoZIhvcNAQEFBQAwgbExCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdHZXJtYW55MQ8wDQYDVQQKEwZCaW50ZWMxCzAJBgNVBAsTAlJEMRUwEwYDVQQDEwwxNzIuMTYuMTA0LjYxGTAXBgNVBAMTEDAwMjkwNzIwMDIwMDAyNTUxDDAKBgNVBAMTAzY3NzEQMA4GA1UEAxMHcnNhLWtleTEQMA4GA1UEAxMHY2FsaW51eDEOMAwGA1UEAxMFTGRhcDIwHhcNMDUwNDExMDgwNzQ0WhcNMDUwNDE4MDgwNzQ0WjCBsTELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0dlcm1hbnkxDzANBgNVBAoTBkJpbnRlYzELMAkGA1UECxMCUkQxFTATBgNVBAMTDDE3Mi4xNi4xMDQuNjEZMBcGA1UEAxMQMDAyOTA3MjAwMjAwMDI1NTEMMAoGA1UEAxMDNjc3MRAwDgYDVQQDEwdyc2Eta2V5MRAwDgYDVQQDEwdjYWxpbnV4MQ4wDAYDVQQDEwVMZGFwMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA8NuMvPN%2Bf8AtK37EdgZ2ztl91LcogD4b1HD05uOtDjoHtJOgjA06wekotGh3B46XBsvrMjuDZwTPjk%2BAxm2KrbT7BdWXJwlefU7F5MP3jZFvZXXzqQCcoV8qCMCPb7WqWiPBunxSnGJBdVeFv8hrUlSeV41d8DieGkeNHne7dCcCAwEAATANBgkqhkiG9w0BAQUFAAOBgQCWClxF2ksyETsW7kF3xRy1urBL4TECGDP9ZPxv1ecMmMMH3TvBtvaumeYfQ52Bzn2B6zijzEVUW6R6%2B1SKh7zd40fVNq6GZcnFZJNwn3uXkEIwwoT2O0YUIegm8 7ChGw3IIeLP%2FSIE%2B2JEjiUzqGB9IqbVr5Q293y5OCvTUVTb%2FDGCAhcwggITAgEBMIHHMIGxMQswCQYDVQQGEwJERTEQMA4GA1UECBMHR2VybWFueTEPMA0GA1UEChMGQmludGVjMQswCQYDVQQLEwJSRDEVMBMGA1UEAxMMMTcyLjE2LjEwNC42MRkwFwYDVQQDExAwMDI5MDcyMDAyMDAwMjU1MQwwCgYDVQQDEwM2NzcxEDAOBgNVBAMTB3JzYS1rZXkxEDAOBgNVBAMTB2NhbGludXgxDjAMBgNVBAMTBUxkYXAyAhEAh%2F%2F4kOpjLLCSkdypLb68YTAMBggqhkiG9w0CBQUAoIGjMBIGCmCGSAGG%2BEUBCQIxBBMCMjAwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAfBgkqhkiG9w0BCQQxEgQQvLmfOp%2F%2FLYNUL1szSn%2BEOTAgBgpghkgBhvhFAQkFMRIEEODa6A8NT%2FkEvkFZ6eclspcwMAYKYIZIAYb4RQEJBzEiEyA4N0ZGRjg5MEVBNjMyQ0IwOTI5MURDQTkyREJFQkM2MTANBgkqhkiG9w0BAQEFAASBgLFndLx8XykdWU7QevIbZyBrTOnS3pGeW1s0sC786r9%2BDbe7LNWPJlDnL1FUmcavFYFIrxP4O4rSxCrLne7TSmfQeJMDSD63TWNt5Ou%2BpwhRQf8PZLeXLzITjg6yQY%2FgVc%2Flf7XIGO%2FUnJHr7q%2FPd%2B6gQAr%2FxTFgpq8WlsfN7s8UAAAAAA%3D%3D
You can download the file used in those examples from here.
The truncated output would look like this (-i in asn1parse added for nicer printing):

> cat request.txt| perl -pe 'use MIME::Base64;s/%([0-9a-f]{2})/sprintf("%s",pack("H2",$1))/eig;$_=MIME::Base64::decode($_);' | openssl asn1parse -i -inform DER | head -n 20 
    0:d=0  hl=2 l=inf  cons: SEQUENCE          
    2:d=1  hl=2 l=   9 prim:  OBJECT            :pkcs7-signedData
   13:d=1  hl=2 l=inf  cons:  cont [ 0 ]        
   15:d=2  hl=4 l=1928 cons:   SEQUENCE          
   19:d=3  hl=2 l=   1 prim:    INTEGER           :01
   22:d=3  hl=2 l=  14 cons:    SET               
   24:d=4  hl=2 l=  12 cons:     SEQUENCE          
   26:d=5  hl=2 l=   8 prim:      OBJECT            :md5
   36:d=5  hl=2 l=   0 prim:      NULL              
   38:d=3  hl=2 l=inf  cons:    SEQUENCE          
   40:d=4  hl=2 l=   9 prim:     OBJECT            :pkcs7-data
   51:d=4  hl=2 l=inf  cons:     cont [ 0 ]        
   53:d=5  hl=4 l= 595 prim:      OCTET STRING      [HEX DUMP]:308006092A864886F70D010703A0803082023C0201003181F83081F5020100305E3059310B3009060355040613024445310F300D060355040A130642696E746563310B3009060355040B13025244310D300B06035504031304726F6F74311D301B06092A864886F70D010901160E726F6F74406C6F63616C686F7374020103300D06092A864886F70D0101010500048180C501DA939AE85DC03CF448010C2B2174D99F457FB224C2D9A7111A203E554B232AC9FC1EED1B30D562F1091D1EC9AFA074242403BACF48172962277A1D6FE6AF5C36476F2E63BE28E75192D9A13A488F4471CFCD839CE5604684688C432BD790DB70E5C50F3BD17074137FAFE75D44DDBBA6262968625DD481BF6F757C39B8723082013A06092A864886F70D010701301106052B0E0302070408A33AD0A0538E7931808201180D378A9310BF719215B08238720D5F4D4E16F59758CA6BF247BD88EA12A8A2098443EBA868FEE91E6C6817A0D25EDEC4F7014CD9BF917BCA7811A323E3A41DAC9C20EA951C80334484571C85D34A3563A7EEEE07080A14AFF8F6B5B1DDA9EBF21B8BB514AB7259F2EFEC4BDFEE13C8B3B00371D5F32A5143FA18606CAB114ABAD54293B3F5F5D2BA1AF03B0DA8D68AE2556F85A68B1A70AE08528EE00634F9F56412D6ED9754EB85653D5549F23A6983552B84DB1EEBC150E1C56C5E225DA98B3301C2E7CEA152BF5D7EFD7C4867D341574D8392B1A7464E880B40AC0687B3ED1ACEB450D1448C4D76D1349ED1898ACF40EF4C9989B92BFE6EE7723672EA70E0A6F423693455B45639B3EE75A309E1D710F21A34CF97FCCD00000000
  652:d=5  hl=2 l=   0 prim:      EOC               
  654:d=4  hl=2 l=   0 prim:     EOC               
  656:d=3  hl=4 l= 748 cons:    cont [ 0 ]        
  660:d=4  hl=4 l= 744 cons:     SEQUENCE          
  664:d=5  hl=4 l= 593 cons:      SEQUENCE          
  668:d=6  hl=2 l=   3 cons:       cont [ 0 ]        
  670:d=7  hl=2 l=   1 prim:        INTEGER           :02
As suggested in the comments using as the last command instead of "openssl asn1parse ..." the command "openssl pkcs7 -inform DER -print_certs -text" gives an even nicer looking output (the same data as previously):

> cat request.txt |\ 
 perl -pe 'use MIME::Base64;s/%([0-9a-f]{2})/sprintf("%s",pack("H2",$1))/eig;$_=MIME::Base64::decode($_);' |\
 openssl pkcs7 -inform DER -print_certs -text
Certificate:

Data:
        Version: 3 (0x2)
        Serial Number:
            87:ff:f8:90:ea:63:2c:b0:92:91:dc:a9:2d:be:bc:61

Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=DE, ST=Germany, O=Bintec, OU=RD, CN=172.16.104.6, CN=0029072002000255, CN=677, CN=rsa-key, CN=calinux, CN=Ldap2
        Validity
            Not Before: Apr 11 08:07:44 2005 GMT
            Not After : Apr 18 08:07:44 2005 GMT
        Subject: C=DE, ST=Germany, O=Bintec, OU=RD, CN=172.16.104.6, CN=0029072002000255, CN=677, CN=rsa-key, CN=calinux, CN=Ldap2
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (1024 bit)
                Modulus:
                    00:f0:db:8c:bc:f3:7e:7f:c0:2d:2b:7e:c4:76:06:
                    76:ce:d9:7d:d4:b7:28:80:3e:1b:d4:70:f4:e6:e3:
                    ad:0e:3a:07:b4:93:a0:8c:0d:3a:c1:e9:28:b4:68:
                    77:07:8e:97:06:cb:eb:32:3b:83:67:04:cf:8e:4f:
                    80:c6:6d:8a:ad:b4:fb:05:d5:97:27:09:5e:7d:4e:
                    c5:e4:c3:f7:8d:91:6f:65:75:f3:a9:00:9c:a1:5f:
                    2a:08:c0:8f:6f:b5:aa:5a:23:c1:ba:7c:52:9c:62:
                    41:75:57:85:bf:c8:6b:52:54:9e:57:8d:5d:f0:38:
                    9e:1a:47:8d:1e:77:bb:74:27
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha1WithRSAEncryption
         96:0a:5c:45:da:4b:32:11:3b:16:ee:41:77:c5:1c:b5:ba:b0:
         4b:e1:31:02:18:33:fd:64:fc:6f:d5:e7:0c:98:c3:07:dd:3b:
         c1:b6:f6:ae:99:e6:1f:43:9d:81:ce:7d:81:eb:38:a3:cc:45:
         54:5b:a4:7a:fb:54:8a:87:bc:dd:e3:47:d5:36:ae:86:65:c9:
         c5:64:93:70:9f:7b:97:90:42:30:c2:84:f6:3b:46:14:21:e8:
         26:f3:b0:a1:1b:0d:c8:21:e2:cf:fd:22:04:fb:62:44:8e:25:
         33:a8:60:7d:22:a6:d5:af:94:36:f7:7c:b9:38:2b:d3:51:54:
         db:fc
-----BEGIN CERTIFICATE-----
MIIC6DCCAlGgAwIBAgIRAIf/+JDqYyywkpHcqS2+vGEwDQYJKoZIhvcNAQEFBQAw
gbExCzAJBgNVBAYTAkRFMRAwDgYDVQQIEwdHZXJtYW55MQ8wDQYDVQQKEwZCaW50
ZWMxCzAJBgNVBAsTAlJEMRUwEwYDVQQDEwwxNzIuMTYuMTA0LjYxGTAXBgNVBAMT
EDAwMjkwNzIwMDIwMDAyNTUxDDAKBgNVBAMTAzY3NzEQMA4GA1UEAxMHcnNhLWtl
eTEQMA4GA1UEAxMHY2FsaW51eDEOMAwGA1UEAxMFTGRhcDIwHhcNMDUwNDExMDgw
NzQ0WhcNMDUwNDE4MDgwNzQ0WjCBsTELMAkGA1UEBhMCREUxEDAOBgNVBAgTB0dl
cm1hbnkxDzANBgNVBAoTBkJpbnRlYzELMAkGA1UECxMCUkQxFTATBgNVBAMTDDE3
Mi4xNi4xMDQuNjEZMBcGA1UEAxMQMDAyOTA3MjAwMjAwMDI1NTEMMAoGA1UEAxMD
Njc3MRAwDgYDVQQDEwdyc2Eta2V5MRAwDgYDVQQDEwdjYWxpbnV4MQ4wDAYDVQQD
EwVMZGFwMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA8NuMvPN+f8AtK37E
dgZ2ztl91LcogD4b1HD05uOtDjoHtJOgjA06wekotGh3B46XBsvrMjuDZwTPjk+A
xm2KrbT7BdWXJwlefU7F5MP3jZFvZXXzqQCcoV8qCMCPb7WqWiPBunxSnGJBdVeF
v8hrUlSeV41d8DieGkeNHne7dCcCAwEAATANBgkqhkiG9w0BAQUFAAOBgQCWClxF
2ksyETsW7kF3xRy1urBL4TECGDP9ZPxv1ecMmMMH3TvBtvaumeYfQ52Bzn2B6zij
zEVUW6R6+1SKh7zd40fVNq6GZcnFZJNwn3uXkEIwwoT2O0YUIegm87ChGw3IIeLP
/SIE+2JEjiUzqGB9IqbVr5Q293y5OCvTUVTb/A==
-----END CERTIFICATE-----

Nagle in OpenSSH

OpenSSH by default enables NODELAY flags on the TCP socket, so each key stroke that you make is send as a separate packet. In some situation it is not a very good idea and you would like to have Nagle algorithm enabled.

Nothing ground braking, you can "enable" it by using a simple script (version written in C which is using TCP_CORK socket option) and ProxyCommand option.

The usage, run ssh command like that (or change your ~/.ssh/config):

ssh -o "proxycommand nagle.py %h %p" user@host

and read man ssh :)

you can modify the Nagle parameters by changing those variables:


  n_l    = 5    # how many timeout do we wait for
  n_tout = 0.1  # actual max wait is n_tout*n_l
  n_size = 1024 # minimum size of the packet

maybe this will be useful for somebody :)


PS. Just to add, there is also a SOCKS client that has Nagle support.

PS2. Interesting socket options in Linux and FreeBSD TCP_CORK and TCP_NOPUSH

PS3. Of course you could also just use socat like this, it also works nicely:
ProxyCommand /usr/bin/socat - TCP:%h:%p,cork

Similar post: SSH over SSL

getting to the IP data encapsulated inside some strange protocol

An example of striping outside encapsulation from the 
packets to get to the IPv4 header inside the packet:

tcpdump -nxr input.pcap | \
perl -e '$i=0;while(<>){if (/^\d/){ $i=0 }; \
if (/0x0000: /) { $i=1;print "\n";}; \
if($i==1){s/^.+?: //;s/(..)(..)\s/$1 $2 /g;print $_;}}' \
| perl -npe 's/^.+? 45 /00000 45 /' | \
| text2pcap -e 0x800 - output.pcap

Nothing ground breaking but could be useful,
 
or a slightly shorter version (added 2012-10-25):
tcpdump -nxr input.pcap |\
perl -ne 'next if (not /^\s+0x0/);chomp;s/^/\n/ if (/0x0000/);\
s/\t+0x.+?:\s+//;s/\ //g;print' |\
perl -pe 's/^.+?4500/4500/;s/(..)/$1 /g;s/^/000000 /' |\
text2pcap -e 0x800 - output.pcap