mod_tcp_chaff.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * mod_tcp_chaff.c
  3. *
  4. * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
  5. *
  6. * $Id$
  7. */
  8. #include "config.h"
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include "pkt.h"
  13. #include "mod.h"
  14. #include "randutil.h"
  15. #include "iputil.h"
  16. #define CHAFF_TYPE_CKSUM 1
  17. #define CHAFF_TYPE_NULL 2
  18. #define CHAFF_TYPE_PAWS 3
  19. #define CHAFF_TYPE_REXMIT 4
  20. #define CHAFF_TYPE_SEQ 5
  21. #define CHAFF_TYPE_SYN 6
  22. #define CHAFF_TYPE_TTL 7
  23. struct tcp_chaff_data {
  24. rand_t *rnd;
  25. int type;
  26. int ttl;
  27. };
  28. void *
  29. tcp_chaff_close(void *d)
  30. {
  31. struct tcp_chaff_data *data = (struct tcp_chaff_data *)d;
  32. if (data != NULL) {
  33. rand_close(data->rnd);
  34. free(data);
  35. }
  36. return (NULL);
  37. }
  38. void *
  39. tcp_chaff_open(int argc, char *argv[])
  40. {
  41. struct tcp_chaff_data *data;
  42. if (argc < 2)
  43. return (NULL);
  44. if ((data = calloc(1, sizeof(*data))) == NULL)
  45. return (NULL);
  46. data->rnd = rand_open();
  47. if (strcasecmp(argv[1], "cksum") == 0)
  48. data->type = CHAFF_TYPE_CKSUM;
  49. else if (strcasecmp(argv[1], "null") == 0)
  50. data->type = CHAFF_TYPE_NULL;
  51. else if (strcasecmp(argv[1], "paws") == 0)
  52. data->type = CHAFF_TYPE_PAWS;
  53. else if (strcasecmp(argv[1], "rexmit") == 0)
  54. data->type = CHAFF_TYPE_REXMIT;
  55. else if (strcasecmp(argv[1], "seq") == 0)
  56. data->type = CHAFF_TYPE_SEQ;
  57. else if (strcasecmp(argv[1], "syn") == 0)
  58. data->type = CHAFF_TYPE_SYN;
  59. else if ((data->ttl = atoi(argv[1])) > 0 && data->ttl < 256)
  60. data->type = CHAFF_TYPE_TTL;
  61. else
  62. return (tcp_chaff_close(data));
  63. return (data);
  64. }
  65. int
  66. tcp_chaff_apply(void *d, struct pktq *pktq)
  67. {
  68. struct tcp_chaff_data *data = (struct tcp_chaff_data *)d;
  69. struct pkt *pkt, *new, *next;
  70. struct tcp_opt opt;
  71. int i;
  72. uint16_t eth_type;
  73. uint8_t nxt;
  74. for (pkt = TAILQ_FIRST(pktq); pkt != TAILQ_END(pktq); pkt = next) {
  75. next = TAILQ_NEXT(pkt, pkt_next);
  76. eth_type = htons(pkt->pkt_eth->eth_type);
  77. if (pkt->pkt_ip == NULL)
  78. continue;
  79. if (eth_type == ETH_TYPE_IP) {
  80. nxt = pkt->pkt_ip->ip_p;
  81. } else if (eth_type == ETH_TYPE_IPV6) {
  82. nxt = pkt->pkt_ip6->ip6_nxt;
  83. } else {
  84. continue;
  85. }
  86. if (nxt != IP_PROTO_TCP ||
  87. pkt->pkt_tcp == NULL || pkt->pkt_tcp_data == NULL ||
  88. (pkt->pkt_tcp->th_flags & TH_ACK) == 0)
  89. continue;
  90. new = pkt_dup(pkt);
  91. rand_strset(data->rnd, new->pkt_tcp_data, new->pkt_end -
  92. new->pkt_tcp_data + 1);
  93. switch (data->type) {
  94. case CHAFF_TYPE_CKSUM:
  95. inet_checksum(eth_type, new->pkt_ip,
  96. new->pkt_ip_data - new->pkt_eth_data);
  97. new->pkt_tcp->th_sum = rand_uint16(data->rnd);
  98. break;
  99. case CHAFF_TYPE_NULL:
  100. new->pkt_tcp->th_flags = 0;
  101. inet_checksum(eth_type, new->pkt_ip,
  102. new->pkt_ip_data - new->pkt_eth_data);
  103. break;
  104. case CHAFF_TYPE_PAWS:
  105. /* Delete any existing TCP options. */
  106. i = (new->pkt_tcp->th_off << 2) - TCP_HDR_LEN;
  107. new->pkt_tcp->th_off = 5;
  108. new->pkt_end -= i;
  109. new->pkt_ip->ip_len = htons(new->pkt_end -
  110. new->pkt_eth_data);
  111. /* Insert initial timestamp, for PAWS elimination. */
  112. opt.opt_type = TCP_OPT_TIMESTAMP;
  113. opt.opt_len = TCP_OPT_LEN + 8;
  114. opt.opt_data.timestamp[0] = 0;
  115. opt.opt_data.timestamp[1] = 0;
  116. if ((i = inet_add_option(eth_type, new->pkt_ip,
  117. PKT_BUF_LEN - ETH_HDR_LEN,
  118. IP_PROTO_TCP, &opt, opt.opt_len)) < 0) {
  119. pkt_free(new);
  120. continue;
  121. }
  122. new->pkt_end += i;
  123. inet_checksum(eth_type, new->pkt_ip,
  124. new->pkt_ip_data - new->pkt_eth_data);
  125. pkt_decorate(new);
  126. break;
  127. case CHAFF_TYPE_REXMIT:
  128. new->pkt_ts.tv_usec = 1;
  129. inet_checksum(eth_type, new->pkt_ip,
  130. new->pkt_ip_data - new->pkt_eth_data);
  131. break;
  132. case CHAFF_TYPE_SEQ:
  133. /* XXX - dunno recv window? */
  134. new->pkt_tcp->th_seq = htonl(666);
  135. new->pkt_tcp->th_ack = htonl(666);
  136. inet_checksum(eth_type, new->pkt_ip,
  137. new->pkt_ip_data - new->pkt_eth_data);
  138. break;
  139. case CHAFF_TYPE_SYN:
  140. new->pkt_tcp->th_flags = TH_SYN;
  141. new->pkt_tcp->th_seq = rand_uint32(data->rnd);
  142. new->pkt_tcp->th_ack = 0;
  143. new->pkt_end = new->pkt_tcp_data;
  144. new->pkt_tcp_data = NULL;
  145. new->pkt_ip->ip_len = htons(new->pkt_end -
  146. new->pkt_eth_data);
  147. inet_checksum(eth_type, new->pkt_ip,
  148. new->pkt_ip_data - new->pkt_eth_data);
  149. break;
  150. case CHAFF_TYPE_TTL:
  151. if (eth_type == ETH_TYPE_IP) {
  152. new->pkt_ip->ip_ttl = data->ttl;
  153. ip_checksum(new->pkt_ip,
  154. new->pkt_ip_data - new->pkt_eth_data);
  155. } else if (eth_type == ETH_TYPE_IPV6) {
  156. new->pkt_ip6->ip6_hlim = data->ttl;
  157. }
  158. break;
  159. }
  160. /* Minimal random reordering. */
  161. if ((new->pkt_tcp->th_sum & 1) == 0)
  162. TAILQ_INSERT_BEFORE(pkt, new, pkt_next);
  163. else
  164. TAILQ_INSERT_AFTER(pktq, pkt, new, pkt_next);
  165. }
  166. return (0);
  167. }
  168. struct mod mod_tcp_chaff = {
  169. "tcp_chaff", /* name */
  170. "tcp_chaff cksum|null|paws|rexmit|seq|syn|<ttl>", /* usage */
  171. tcp_chaff_open, /* open */
  172. tcp_chaff_apply, /* apply */
  173. tcp_chaff_close /* close */
  174. };