Skip to content

Instantly share code, notes, and snippets.

@indutny
Last active August 29, 2015 14:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save indutny/6aee5191d8d6e8ad886f to your computer and use it in GitHub Desktop.
Save indutny/6aee5191d8d6e8ad886f to your computer and use it in GitHub Desktop.
#!/usr/sbin/dtrace -C -s
#pragma D option quiet
#pragma D option strsize=4096
#define PTR__SIZE sizeof(uint64_t)
struct SSL {
uint32_t version;
uint8_t pad[0x12c];
uint64_t session;
};
struct SSL_SESSION {
uint8_t pad[0x118];
uint64_t hostname;
};
struct STACK_OF {
uint32_t num;
uint8_t pad[4];
uint64_t data;
};
struct SSL_CIPHER {
uint32_t valid;
uint8_t pad[4];
uint64_t name;
};
pid*::ssl3_choose_cipher:entry
{
this->ssl = (struct SSL*) copyin(arg0, sizeof(struct SSL));
this->version = this->ssl->version;
this->session = this->ssl->session != 0 ?
(struct SSL_SESSION*) copyin(this->ssl->session,
sizeof(struct SSL_SESSION)) :
NULL;
this->host_ptr = this->session != NULL ? this->session->hostname : 0;
this->host = this->host_ptr != 0 ? copyinstr(this->host_ptr, 256) : "";
this->stack_of = (struct STACK_OF*) copyin(arg1, sizeof(struct STACK_OF));
this->num = this->stack_of->num;
this->left = this->num;
this->data = (uint64_t*) copyin(this->stack_of->data, PTR__SIZE * this->num);
this->pending = 1;
this->buf = "";
}
#define LOOP_BODY(INDEX) \
pid*::ssl3_choose_cipher:entry \
/this->pending && this->left == (INDEX)/ \
{ \
this->left--; \
this->cipher = (struct SSL_CIPHER*) copyin(this->data[this->left], \
sizeof(struct SSL_CIPHER)); \
this->cipher_name = copyinstr(this->cipher->name, 256); \
this->buf = strjoin(this->buf, this->cipher_name); \
this->buf = strjoin(this->buf, ":"); \
}
#define LOOP__4(off) \
LOOP_BODY(off + 3) \
LOOP_BODY(off + 2) \
LOOP_BODY(off + 1) \
LOOP_BODY(off + 0)
#define LOOP__16(off) \
LOOP__4(off + 12) \
LOOP__4(off + 8) \
LOOP__4(off + 4) \
LOOP__4(off + 0)
#define LOOP__64(off) \
LOOP__16(off + 48) \
LOOP__16(off + 32) \
LOOP__16(off + 16) \
LOOP__16(off + 0)
#define LOOP__256(off) \
LOOP__64(off + 192) \
LOOP__64(off + 128) \
LOOP__64(off + 64) \
LOOP__64(off + 0)
LOOP__16(1)
pid*::ssl3_choose_cipher:entry
/this->pending == 1/
{
this->pending = 0;
printf("type=ciphers num=%d version=\"%04x\" host=\"%s\" value=\"%s\"\n",
this->num,
this->version,
this->host,
this->buf);
}
pid*::ssl3_choose_cipher:entry
{
this->ssl = 0;
this->session = 0;
this->host_ptr = 0;
this->host = 0;
this->version = 0;
this->left = 0;
this->num = 0;
this->data = 0;
this->cipher = 0;
this->pending = 0;
this->cipher_name_ptr = 0;
this->cipher_name = 0;
}
var fs = require('fs');
var util = require('util');
var map = {};
var count = 0;
function onLine(line) {
if (!line)
return;
var match = line.match(
/type=ciphers num=(\d+) version="([^"]*)" host="([^"]*)" value="([^"]*)"/
);
if (!match)
return;
var num = match[1] | 0;
var version = match[2];
var hasSNI = match[3] !== '';
var value = match[4];
var key = version + '/' + hasSNI + '/' + value;
if (map[key])
map[key].count++;
else
map[key] = { version: version, hasSNI: hasSNI, value: value, count: 1 };
count++;
}
function print(type) {
var out = Object.keys(map).sort(function(a, b) {
return map[b].count - map[a].count;
}).map(function(key) {
var item = map[key];
return util.format('count=%d version=%j sni=%j value=%j',
item.count,
item.version,
item.hasSNI,
item.value);
}).join('\n');
if (type === 'log')
console.log(out);
else if (type === 'error')
console.error(out);
}
var chunks = '';
process.stdin.on('data', function(chunk) {
chunks += chunk;
if (!/\n/.test(chunks))
return;
var split = chunks.split(/\n/g);
chunks = split.pop();
split.forEach(onLine);
});
process.stdin.resume();
process.on('SIGINT', function() {
print('log');
process.exit(0);
});
process.on('SIGUSR2', function() {
print('error');
});
setInterval(function() {
console.error('count=' + count);
}, 5000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment