1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2013 Patrick McHardy <kaber@trash.net> 4 */ 5 6 #include <linux/module.h> 7 #include <linux/skbuff.h> 8 #include <asm/unaligned.h> 9 #include <net/tcp.h> 10 #include <net/netns/generic.h> 11 #include <linux/proc_fs.h> 12 13 #include <linux/netfilter_ipv6.h> 14 #include <linux/netfilter/nf_synproxy.h> 15 16 #include <net/netfilter/nf_conntrack.h> 17 #include <net/netfilter/nf_conntrack_ecache.h> 18 #include <net/netfilter/nf_conntrack_extend.h> 19 #include <net/netfilter/nf_conntrack_seqadj.h> 20 #include <net/netfilter/nf_conntrack_synproxy.h> 21 #include <net/netfilter/nf_conntrack_zones.h> 22 #include <net/netfilter/nf_synproxy.h> 23 24 unsigned int synproxy_net_id; 25 EXPORT_SYMBOL_GPL(synproxy_net_id); 26 27 bool 28 synproxy_parse_options(const struct sk_buff *skb, unsigned int doff, 29 const struct tcphdr *th, struct synproxy_options *opts) 30 { 31 int length = (th->doff * 4) - sizeof(*th); 32 u8 buf[40], *ptr; 33 34 ptr = skb_header_pointer(skb, doff + sizeof(*th), length, buf); 35 if (ptr == NULL) 36 return false; 37 38 opts->options = 0; 39 while (length > 0) { 40 int opcode = *ptr++; 41 int opsize; 42 43 switch (opcode) { 44 case TCPOPT_EOL: 45 return true; 46 case TCPOPT_NOP: 47 length--; 48 continue; 49 default: 50 opsize = *ptr++; 51 if (opsize < 2) 52 return true; 53 if (opsize > length) 54 return true; 55 56 switch (opcode) { 57 case TCPOPT_MSS: 58 if (opsize == TCPOLEN_MSS) { 59 opts->mss_option = get_unaligned_be16(ptr); 60 opts->options |= NF_SYNPROXY_OPT_MSS; 61 } 62 break; 63 case TCPOPT_WINDOW: 64 if (opsize == TCPOLEN_WINDOW) { 65 opts->wscale = *ptr; 66 if (opts->wscale > TCP_MAX_WSCALE) 67 opts->wscale = TCP_MAX_WSCALE; 68 opts->options |= NF_SYNPROXY_OPT_WSCALE; 69 } 70 break; 71 case TCPOPT_TIMESTAMP: 72 if (opsize == TCPOLEN_TIMESTAMP) { 73 opts->tsval = get_unaligned_be32(ptr); 74 opts->tsecr = get_unaligned_be32(ptr + 4); 75 opts->options |= NF_SYNPROXY_OPT_TIMESTAMP; 76 } 77 break; 78 case TCPOPT_SACK_PERM: 79 if (opsize == TCPOLEN_SACK_PERM) 80 opts->options |= NF_SYNPROXY_OPT_SACK_PERM; 81 break; 82 } 83 84 ptr += opsize - 2; 85 length -= opsize; 86 } 87 } 88 return true; 89 } 90 EXPORT_SYMBOL_GPL(synproxy_parse_options); 91 92 static unsigned int 93 synproxy_options_size(const struct synproxy_options *opts) 94 { 95 unsigned int size = 0; 96 97 if (opts->options & NF_SYNPROXY_OPT_MSS) 98 size += TCPOLEN_MSS_ALIGNED; 99 if (opts->options & NF_SYNPROXY_OPT_TIMESTAMP) 100 size += TCPOLEN_TSTAMP_ALIGNED; 101 else if (opts->options & NF_SYNPROXY_OPT_SACK_PERM) 102 size += TCPOLEN_SACKPERM_ALIGNED; 103 if (opts->options & NF_SYNPROXY_OPT_WSCALE) 104 size += TCPOLEN_WSCALE_ALIGNED; 105 106 return size; 107 } 108 109 static void 110 synproxy_build_options(struct tcphdr *th, const struct synproxy_options *opts) 111 { 112 __be32 *ptr = (__be32 *)(th + 1); 113 u8 options = opts->options; 114 115 if (options & NF_SYNPROXY_OPT_MSS) 116 *ptr++ = htonl((TCPOPT_MSS << 24) | 117 (TCPOLEN_MSS << 16) | 118 opts->mss_option); 119 120 if (options & NF_SYNPROXY_OPT_TIMESTAMP) { 121 if (options & NF_SYNPROXY_OPT_SACK_PERM) 122 *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | 123 (TCPOLEN_SACK_PERM << 16) | 124 (TCPOPT_TIMESTAMP << 8) | 125 TCPOLEN_TIMESTAMP); 126 else 127 *ptr++ = htonl((TCPOPT_NOP << 24) | 128 (TCPOPT_NOP << 16) | 129 (TCPOPT_TIMESTAMP << 8) | 130 TCPOLEN_TIMESTAMP); 131 132 *ptr++ = htonl(opts->tsval); 133 *ptr++ = htonl(opts->tsecr); 134 } else if (options & NF_SYNPROXY_OPT_SACK_PERM) 135 *ptr++ = htonl((TCPOPT_NOP << 24) | 136 (TCPOPT_NOP << 16) | 137 (TCPOPT_SACK_PERM << 8) | 138 TCPOLEN_SACK_PERM); 139 140 if (options & NF_SYNPROXY_OPT_WSCALE) 141 *ptr++ = htonl((TCPOPT_NOP << 24) | 142 (TCPOPT_WINDOW << 16) | 143 (TCPOLEN_WINDOW << 8) | 144 opts->wscale); 145 } 146 147 void synproxy_init_timestamp_cookie(const struct nf_synproxy_info *info, 148 struct synproxy_options *opts) 149 { 150 opts->tsecr = opts->tsval; 151 opts->tsval = tcp_time_stamp_raw() & ~0x3f; 152 153 if (opts->options & NF_SYNPROXY_OPT_WSCALE) { 154 opts->tsval |= opts->wscale; 155 opts->wscale = info->wscale; 156 } else 157 opts->tsval |= 0xf; 158 159 if (opts->options & NF_SYNPROXY_OPT_SACK_PERM) 160 opts->tsval |= 1 << 4; 161 162 if (opts->options & NF_SYNPROXY_OPT_ECN) 163 opts->tsval |= 1 << 5; 164 } 165 EXPORT_SYMBOL_GPL(synproxy_init_timestamp_cookie); 166 167 static void 168 synproxy_check_timestamp_cookie(struct synproxy_options *opts) 169 { 170 opts->wscale = opts->tsecr & 0xf; 171 if (opts->wscale != 0xf) 172 opts->options |= NF_SYNPROXY_OPT_WSCALE; 173 174 opts->options |= opts->tsecr & (1 << 4) ? NF_SYNPROXY_OPT_SACK_PERM : 0; 175 176 opts->options |= opts->tsecr & (1 << 5) ? NF_SYNPROXY_OPT_ECN : 0; 177 } 178 179 static unsigned int 180 synproxy_tstamp_adjust(struct sk_buff *skb, unsigned int protoff, 181 struct tcphdr *th, struct nf_conn *ct, 182 enum ip_conntrack_info ctinfo, 183 const struct nf_conn_synproxy *synproxy) 184 { 185 unsigned int optoff, optend; 186 __be32 *ptr, old; 187 188 if (synproxy->tsoff == 0) 189 return 1; 190 191 optoff = protoff + sizeof(struct tcphdr); 192 optend = protoff + th->doff * 4; 193 194 if (skb_ensure_writable(skb, optend)) 195 return 0; 196 197 while (optoff < optend) { 198 unsigned char *op = skb->data + optoff; 199 200 switch (op[0]) { 201 case TCPOPT_EOL: 202 return 1; 203 case TCPOPT_NOP: 204 optoff++; 205 continue; 206 default: 207 if (optoff + 1 == optend || 208 optoff + op[1] > optend || 209 op[1] < 2) 210 return 0; 211 if (op[0] == TCPOPT_TIMESTAMP && 212 op[1] == TCPOLEN_TIMESTAMP) { 213 if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY) { 214 ptr = (__be32 *)&op[2]; 215 old = *ptr; 216 *ptr = htonl(ntohl(*ptr) - 217 synproxy->tsoff); 218 } else { 219 ptr = (__be32 *)&op[6]; 220 old = *ptr; 221 *ptr = htonl(ntohl(*ptr) + 222 synproxy->tsoff); 223 } 224 inet_proto_csum_replace4(&th->check, skb, 225 old, *ptr, false); 226 return 1; 227 } 228 optoff += op[1]; 229 } 230 } 231 return 1; 232 } 233 234 static struct nf_ct_ext_type nf_ct_synproxy_extend __read_mostly = { 235 .len = sizeof(struct nf_conn_synproxy), 236 .align = __alignof__(struct nf_conn_synproxy), 237 .id = NF_CT_EXT_SYNPROXY, 238 }; 239 240 #ifdef CONFIG_PROC_FS 241 static void *synproxy_cpu_seq_start(struct seq_file *seq, loff_t *pos) 242 { 243 struct synproxy_net *snet = synproxy_pernet(seq_file_net(seq)); 244 int cpu; 245 246 if (*pos == 0) 247 return SEQ_START_TOKEN; 248 249 for (cpu = *pos - 1; cpu < nr_cpu_ids; cpu++) { 250 if (!cpu_possible(cpu)) 251 continue; 252 *pos = cpu + 1; 253 return per_cpu_ptr(snet->stats, cpu); 254 } 255 256 return NULL; 257 } 258 259 static void *synproxy_cpu_seq_next(struct seq_file *seq, void *v, loff_t *pos) 260 { 261 struct synproxy_net *snet = synproxy_pernet(seq_file_net(seq)); 262 int cpu; 263 264 for (cpu = *pos; cpu < nr_cpu_ids; cpu++) { 265 if (!cpu_possible(cpu)) 266 continue; 267 *pos = cpu + 1; 268 return per_cpu_ptr(snet->stats, cpu); 269 } 270 (*pos)++; 271 return NULL; 272 } 273 274 static void synproxy_cpu_seq_stop(struct seq_file *seq, void *v) 275 { 276 return; 277 } 278 279 static int synproxy_cpu_seq_show(struct seq_file *seq, void *v) 280 { 281 struct synproxy_stats *stats = v; 282 283 if (v == SEQ_START_TOKEN) { 284 seq_puts(seq, "entries\t\tsyn_received\t" 285 "cookie_invalid\tcookie_valid\t" 286 "cookie_retrans\tconn_reopened\n"); 287 return 0; 288 } 289 290 seq_printf(seq, "%08x\t%08x\t%08x\t%08x\t%08x\t%08x\n", 0, 291 stats->syn_received, 292 stats->cookie_invalid, 293 stats->cookie_valid, 294 stats->cookie_retrans, 295 stats->conn_reopened); 296 297 return 0; 298 } 299 300 static const struct seq_operations synproxy_cpu_seq_ops = { 301 .start = synproxy_cpu_seq_start, 302 .next = synproxy_cpu_seq_next, 303 .stop = synproxy_cpu_seq_stop, 304 .show = synproxy_cpu_seq_show, 305 }; 306 307 static int __net_init synproxy_proc_init(struct net *net) 308 { 309 if (!proc_create_net("synproxy", 0444, net->proc_net_stat, 310 &synproxy_cpu_seq_ops, sizeof(struct seq_net_private))) 311 return -ENOMEM; 312 return 0; 313 } 314 315 static void __net_exit synproxy_proc_exit(struct net *net) 316 { 317 remove_proc_entry("synproxy", net->proc_net_stat); 318 } 319 #else 320 static int __net_init synproxy_proc_init(struct net *net) 321 { 322 return 0; 323 } 324 325 static void __net_exit synproxy_proc_exit(struct net *net) 326 { 327 return; 328 } 329 #endif /* CONFIG_PROC_FS */ 330 331 static int __net_init synproxy_net_init(struct net *net) 332 { 333 struct synproxy_net *snet = synproxy_pernet(net); 334 struct nf_conn *ct; 335 int err = -ENOMEM; 336 337 ct = nf_ct_tmpl_alloc(net, &nf_ct_zone_dflt, GFP_KERNEL); 338 if (!ct) 339 goto err1; 340 341 if (!nfct_seqadj_ext_add(ct)) 342 goto err2; 343 if (!nfct_synproxy_ext_add(ct)) 344 goto err2; 345 346 __set_bit(IPS_CONFIRMED_BIT, &ct->status); 347 nf_conntrack_get(&ct->ct_general); 348 snet->tmpl = ct; 349 350 snet->stats = alloc_percpu(struct synproxy_stats); 351 if (snet->stats == NULL) 352 goto err2; 353 354 err = synproxy_proc_init(net); 355 if (err < 0) 356 goto err3; 357 358 return 0; 359 360 err3: 361 free_percpu(snet->stats); 362 err2: 363 nf_ct_tmpl_free(ct); 364 err1: 365 return err; 366 } 367 368 static void __net_exit synproxy_net_exit(struct net *net) 369 { 370 struct synproxy_net *snet = synproxy_pernet(net); 371 372 nf_ct_put(snet->tmpl); 373 synproxy_proc_exit(net); 374 free_percpu(snet->stats); 375 } 376 377 static struct pernet_operations synproxy_net_ops = { 378 .init = synproxy_net_init, 379 .exit = synproxy_net_exit, 380 .id = &synproxy_net_id, 381 .size = sizeof(struct synproxy_net), 382 }; 383 384 static int __init synproxy_core_init(void) 385 { 386 int err; 387 388 err = nf_ct_extend_register(&nf_ct_synproxy_extend); 389 if (err < 0) 390 goto err1; 391 392 err = register_pernet_subsys(&synproxy_net_ops); 393 if (err < 0) 394 goto err2; 395 396 return 0; 397 398 err2: 399 nf_ct_extend_unregister(&nf_ct_synproxy_extend); 400 err1: 401 return err; 402 } 403 404 static void __exit synproxy_core_exit(void) 405 { 406 unregister_pernet_subsys(&synproxy_net_ops); 407 nf_ct_extend_unregister(&nf_ct_synproxy_extend); 408 } 409 410 module_init(synproxy_core_init); 411 module_exit(synproxy_core_exit); 412 413 static struct iphdr * 414 synproxy_build_ip(struct net *net, struct sk_buff *skb, __be32 saddr, 415 __be32 daddr) 416 { 417 struct iphdr *iph; 418 419 skb_reset_network_header(skb); 420 iph = skb_put(skb, sizeof(*iph)); 421 iph->version = 4; 422 iph->ihl = sizeof(*iph) / 4; 423 iph->tos = 0; 424 iph->id = 0; 425 iph->frag_off = htons(IP_DF); 426 iph->ttl = net->ipv4.sysctl_ip_default_ttl; 427 iph->protocol = IPPROTO_TCP; 428 iph->check = 0; 429 iph->saddr = saddr; 430 iph->daddr = daddr; 431 432 return iph; 433 } 434 435 static void 436 synproxy_send_tcp(struct net *net, 437 const struct sk_buff *skb, struct sk_buff *nskb, 438 struct nf_conntrack *nfct, enum ip_conntrack_info ctinfo, 439 struct iphdr *niph, struct tcphdr *nth, 440 unsigned int tcp_hdr_size) 441 { 442 nth->check = ~tcp_v4_check(tcp_hdr_size, niph->saddr, niph->daddr, 0); 443 nskb->ip_summed = CHECKSUM_PARTIAL; 444 nskb->csum_start = (unsigned char *)nth - nskb->head; 445 nskb->csum_offset = offsetof(struct tcphdr, check); 446 447 skb_dst_set_noref(nskb, skb_dst(skb)); 448 nskb->protocol = htons(ETH_P_IP); 449 if (ip_route_me_harder(net, nskb->sk, nskb, RTN_UNSPEC)) 450 goto free_nskb; 451 452 if (nfct) { 453 nf_ct_set(nskb, (struct nf_conn *)nfct, ctinfo); 454 nf_conntrack_get(nfct); 455 } 456 457 ip_local_out(net, nskb->sk, nskb); 458 return; 459 460 free_nskb: 461 kfree_skb(nskb); 462 } 463 464 void 465 synproxy_send_client_synack(struct net *net, 466 const struct sk_buff *skb, const struct tcphdr *th, 467 const struct synproxy_options *opts) 468 { 469 struct sk_buff *nskb; 470 struct iphdr *iph, *niph; 471 struct tcphdr *nth; 472 unsigned int tcp_hdr_size; 473 u16 mss = opts->mss_encode; 474 475 iph = ip_hdr(skb); 476 477 tcp_hdr_size = sizeof(*nth) + synproxy_options_size(opts); 478 nskb = alloc_skb(sizeof(*niph) + tcp_hdr_size + MAX_TCP_HEADER, 479 GFP_ATOMIC); 480 if (!nskb) 481 return; 482 skb_reserve(nskb, MAX_TCP_HEADER); 483 484 niph = synproxy_build_ip(net, nskb, iph->daddr, iph->saddr); 485 486 skb_reset_transport_header(nskb); 487 nth = skb_put(nskb, tcp_hdr_size); 488 nth->source = th->dest; 489 nth->dest = th->source; 490 nth->seq = htonl(__cookie_v4_init_sequence(iph, th, &mss)); 491 nth->ack_seq = htonl(ntohl(th->seq) + 1); 492 tcp_flag_word(nth) = TCP_FLAG_SYN | TCP_FLAG_ACK; 493 if (opts->options & NF_SYNPROXY_OPT_ECN) 494 tcp_flag_word(nth) |= TCP_FLAG_ECE; 495 nth->doff = tcp_hdr_size / 4; 496 nth->window = 0; 497 nth->check = 0; 498 nth->urg_ptr = 0; 499 500 synproxy_build_options(nth, opts); 501 502 synproxy_send_tcp(net, skb, nskb, skb_nfct(skb), 503 IP_CT_ESTABLISHED_REPLY, niph, nth, tcp_hdr_size); 504 } 505 EXPORT_SYMBOL_GPL(synproxy_send_client_synack); 506 507 static void 508 synproxy_send_server_syn(struct net *net, 509 const struct sk_buff *skb, const struct tcphdr *th, 510 const struct synproxy_options *opts, u32 recv_seq) 511 { 512 struct synproxy_net *snet = synproxy_pernet(net); 513 struct sk_buff *nskb; 514 struct iphdr *iph, *niph; 515 struct tcphdr *nth; 516 unsigned int tcp_hdr_size; 517 518 iph = ip_hdr(skb); 519 520 tcp_hdr_size = sizeof(*nth) + synproxy_options_size(opts); 521 nskb = alloc_skb(sizeof(*niph) + tcp_hdr_size + MAX_TCP_HEADER, 522 GFP_ATOMIC); 523 if (!nskb) 524 return; 525 skb_reserve(nskb, MAX_TCP_HEADER); 526 527 niph = synproxy_build_ip(net, nskb, iph->saddr, iph->daddr); 528 529 skb_reset_transport_header(nskb); 530 nth = skb_put(nskb, tcp_hdr_size); 531 nth->source = th->source; 532 nth->dest = th->dest; 533 nth->seq = htonl(recv_seq - 1); 534 /* ack_seq is used to relay our ISN to the synproxy hook to initialize 535 * sequence number translation once a connection tracking entry exists. 536 */ 537 nth->ack_seq = htonl(ntohl(th->ack_seq) - 1); 538 tcp_flag_word(nth) = TCP_FLAG_SYN; 539 if (opts->options & NF_SYNPROXY_OPT_ECN) 540 tcp_flag_word(nth) |= TCP_FLAG_ECE | TCP_FLAG_CWR; 541 nth->doff = tcp_hdr_size / 4; 542 nth->window = th->window; 543 nth->check = 0; 544 nth->urg_ptr = 0; 545 546 synproxy_build_options(nth, opts); 547 548 synproxy_send_tcp(net, skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW, 549 niph, nth, tcp_hdr_size); 550 } 551 552 static void 553 synproxy_send_server_ack(struct net *net, 554 const struct ip_ct_tcp *state, 555 const struct sk_buff *skb, const struct tcphdr *th, 556 const struct synproxy_options *opts) 557 { 558 struct sk_buff *nskb; 559 struct iphdr *iph, *niph; 560 struct tcphdr *nth; 561 unsigned int tcp_hdr_size; 562 563 iph = ip_hdr(skb); 564 565 tcp_hdr_size = sizeof(*nth) + synproxy_options_size(opts); 566 nskb = alloc_skb(sizeof(*niph) + tcp_hdr_size + MAX_TCP_HEADER, 567 GFP_ATOMIC); 568 if (!nskb) 569 return; 570 skb_reserve(nskb, MAX_TCP_HEADER); 571 572 niph = synproxy_build_ip(net, nskb, iph->daddr, iph->saddr); 573 574 skb_reset_transport_header(nskb); 575 nth = skb_put(nskb, tcp_hdr_size); 576 nth->source = th->dest; 577 nth->dest = th->source; 578 nth->seq = htonl(ntohl(th->ack_seq)); 579 nth->ack_seq = htonl(ntohl(th->seq) + 1); 580 tcp_flag_word(nth) = TCP_FLAG_ACK; 581 nth->doff = tcp_hdr_size / 4; 582 nth->window = htons(state->seen[IP_CT_DIR_ORIGINAL].td_maxwin); 583 nth->check = 0; 584 nth->urg_ptr = 0; 585 586 synproxy_build_options(nth, opts); 587 588 synproxy_send_tcp(net, skb, nskb, NULL, 0, niph, nth, tcp_hdr_size); 589 } 590 591 static void 592 synproxy_send_client_ack(struct net *net, 593 const struct sk_buff *skb, const struct tcphdr *th, 594 const struct synproxy_options *opts) 595 { 596 struct sk_buff *nskb; 597 struct iphdr *iph, *niph; 598 struct tcphdr *nth; 599 unsigned int tcp_hdr_size; 600 601 iph = ip_hdr(skb); 602 603 tcp_hdr_size = sizeof(*nth) + synproxy_options_size(opts); 604 nskb = alloc_skb(sizeof(*niph) + tcp_hdr_size + MAX_TCP_HEADER, 605 GFP_ATOMIC); 606 if (!nskb) 607 return; 608 skb_reserve(nskb, MAX_TCP_HEADER); 609 610 niph = synproxy_build_ip(net, nskb, iph->saddr, iph->daddr); 611 612 skb_reset_transport_header(nskb); 613 nth = skb_put(nskb, tcp_hdr_size); 614 nth->source = th->source; 615 nth->dest = th->dest; 616 nth->seq = htonl(ntohl(th->seq) + 1); 617 nth->ack_seq = th->ack_seq; 618 tcp_flag_word(nth) = TCP_FLAG_ACK; 619 nth->doff = tcp_hdr_size / 4; 620 nth->window = htons(ntohs(th->window) >> opts->wscale); 621 nth->check = 0; 622 nth->urg_ptr = 0; 623 624 synproxy_build_options(nth, opts); 625 626 synproxy_send_tcp(net, skb, nskb, skb_nfct(skb), 627 IP_CT_ESTABLISHED_REPLY, niph, nth, tcp_hdr_size); 628 } 629 630 bool 631 synproxy_recv_client_ack(struct net *net, 632 const struct sk_buff *skb, const struct tcphdr *th, 633 struct synproxy_options *opts, u32 recv_seq) 634 { 635 struct synproxy_net *snet = synproxy_pernet(net); 636 int mss; 637 638 mss = __cookie_v4_check(ip_hdr(skb), th, ntohl(th->ack_seq) - 1); 639 if (mss == 0) { 640 this_cpu_inc(snet->stats->cookie_invalid); 641 return false; 642 } 643 644 this_cpu_inc(snet->stats->cookie_valid); 645 opts->mss_option = mss; 646 opts->options |= NF_SYNPROXY_OPT_MSS; 647 648 if (opts->options & NF_SYNPROXY_OPT_TIMESTAMP) 649 synproxy_check_timestamp_cookie(opts); 650 651 synproxy_send_server_syn(net, skb, th, opts, recv_seq); 652 return true; 653 } 654 EXPORT_SYMBOL_GPL(synproxy_recv_client_ack); 655 656 unsigned int 657 ipv4_synproxy_hook(void *priv, struct sk_buff *skb, 658 const struct nf_hook_state *nhs) 659 { 660 struct net *net = nhs->net; 661 struct synproxy_net *snet = synproxy_pernet(net); 662 enum ip_conntrack_info ctinfo; 663 struct nf_conn *ct; 664 struct nf_conn_synproxy *synproxy; 665 struct synproxy_options opts = {}; 666 const struct ip_ct_tcp *state; 667 struct tcphdr *th, _th; 668 unsigned int thoff; 669 670 ct = nf_ct_get(skb, &ctinfo); 671 if (!ct) 672 return NF_ACCEPT; 673 674 synproxy = nfct_synproxy(ct); 675 if (!synproxy) 676 return NF_ACCEPT; 677 678 if (nf_is_loopback_packet(skb) || 679 ip_hdr(skb)->protocol != IPPROTO_TCP) 680 return NF_ACCEPT; 681 682 thoff = ip_hdrlen(skb); 683 th = skb_header_pointer(skb, thoff, sizeof(_th), &_th); 684 if (!th) 685 return NF_DROP; 686 687 state = &ct->proto.tcp; 688 switch (state->state) { 689 case TCP_CONNTRACK_CLOSE: 690 if (th->rst && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) { 691 nf_ct_seqadj_init(ct, ctinfo, synproxy->isn - 692 ntohl(th->seq) + 1); 693 break; 694 } 695 696 if (!th->syn || th->ack || 697 CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) 698 break; 699 700 /* Reopened connection - reset the sequence number and timestamp 701 * adjustments, they will get initialized once the connection is 702 * reestablished. 703 */ 704 nf_ct_seqadj_init(ct, ctinfo, 0); 705 synproxy->tsoff = 0; 706 this_cpu_inc(snet->stats->conn_reopened); 707 fallthrough; 708 case TCP_CONNTRACK_SYN_SENT: 709 if (!synproxy_parse_options(skb, thoff, th, &opts)) 710 return NF_DROP; 711 712 if (!th->syn && th->ack && 713 CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) { 714 /* Keep-Alives are sent with SEG.SEQ = SND.NXT-1, 715 * therefore we need to add 1 to make the SYN sequence 716 * number match the one of first SYN. 717 */ 718 if (synproxy_recv_client_ack(net, skb, th, &opts, 719 ntohl(th->seq) + 1)) { 720 this_cpu_inc(snet->stats->cookie_retrans); 721 consume_skb(skb); 722 return NF_STOLEN; 723 } else { 724 return NF_DROP; 725 } 726 } 727 728 synproxy->isn = ntohl(th->ack_seq); 729 if (opts.options & NF_SYNPROXY_OPT_TIMESTAMP) 730 synproxy->its = opts.tsecr; 731 732 nf_conntrack_event_cache(IPCT_SYNPROXY, ct); 733 break; 734 case TCP_CONNTRACK_SYN_RECV: 735 if (!th->syn || !th->ack) 736 break; 737 738 if (!synproxy_parse_options(skb, thoff, th, &opts)) 739 return NF_DROP; 740 741 if (opts.options & NF_SYNPROXY_OPT_TIMESTAMP) { 742 synproxy->tsoff = opts.tsval - synproxy->its; 743 nf_conntrack_event_cache(IPCT_SYNPROXY, ct); 744 } 745 746 opts.options &= ~(NF_SYNPROXY_OPT_MSS | 747 NF_SYNPROXY_OPT_WSCALE | 748 NF_SYNPROXY_OPT_SACK_PERM); 749 750 swap(opts.tsval, opts.tsecr); 751 synproxy_send_server_ack(net, state, skb, th, &opts); 752 753 nf_ct_seqadj_init(ct, ctinfo, synproxy->isn - ntohl(th->seq)); 754 nf_conntrack_event_cache(IPCT_SEQADJ, ct); 755 756 swap(opts.tsval, opts.tsecr); 757 synproxy_send_client_ack(net, skb, th, &opts); 758 759 consume_skb(skb); 760 return NF_STOLEN; 761 default: 762 break; 763 } 764 765 synproxy_tstamp_adjust(skb, thoff, th, ct, ctinfo, synproxy); 766 return NF_ACCEPT; 767 } 768 EXPORT_SYMBOL_GPL(ipv4_synproxy_hook); 769 770 static const struct nf_hook_ops ipv4_synproxy_ops[] = { 771 { 772 .hook = ipv4_synproxy_hook, 773 .pf = NFPROTO_IPV4, 774 .hooknum = NF_INET_LOCAL_IN, 775 .priority = NF_IP_PRI_CONNTRACK_CONFIRM - 1, 776 }, 777 { 778 .hook = ipv4_synproxy_hook, 779 .pf = NFPROTO_IPV4, 780 .hooknum = NF_INET_POST_ROUTING, 781 .priority = NF_IP_PRI_CONNTRACK_CONFIRM - 1, 782 }, 783 }; 784 785 int nf_synproxy_ipv4_init(struct synproxy_net *snet, struct net *net) 786 { 787 int err; 788 789 if (snet->hook_ref4 == 0) { 790 err = nf_register_net_hooks(net, ipv4_synproxy_ops, 791 ARRAY_SIZE(ipv4_synproxy_ops)); 792 if (err) 793 return err; 794 } 795 796 snet->hook_ref4++; 797 return 0; 798 } 799 EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_init); 800 801 void nf_synproxy_ipv4_fini(struct synproxy_net *snet, struct net *net) 802 { 803 snet->hook_ref4--; 804 if (snet->hook_ref4 == 0) 805 nf_unregister_net_hooks(net, ipv4_synproxy_ops, 806 ARRAY_SIZE(ipv4_synproxy_ops)); 807 } 808 EXPORT_SYMBOL_GPL(nf_synproxy_ipv4_fini); 809 810 #if IS_ENABLED(CONFIG_IPV6) 811 static struct ipv6hdr * 812 synproxy_build_ip_ipv6(struct net *net, struct sk_buff *skb, 813 const struct in6_addr *saddr, 814 const struct in6_addr *daddr) 815 { 816 struct ipv6hdr *iph; 817 818 skb_reset_network_header(skb); 819 iph = skb_put(skb, sizeof(*iph)); 820 ip6_flow_hdr(iph, 0, 0); 821 iph->hop_limit = net->ipv6.devconf_all->hop_limit; 822 iph->nexthdr = IPPROTO_TCP; 823 iph->saddr = *saddr; 824 iph->daddr = *daddr; 825 826 return iph; 827 } 828 829 static void 830 synproxy_send_tcp_ipv6(struct net *net, 831 const struct sk_buff *skb, struct sk_buff *nskb, 832 struct nf_conntrack *nfct, enum ip_conntrack_info ctinfo, 833 struct ipv6hdr *niph, struct tcphdr *nth, 834 unsigned int tcp_hdr_size) 835 { 836 struct dst_entry *dst; 837 struct flowi6 fl6; 838 int err; 839 840 nth->check = ~tcp_v6_check(tcp_hdr_size, &niph->saddr, &niph->daddr, 0); 841 nskb->ip_summed = CHECKSUM_PARTIAL; 842 nskb->csum_start = (unsigned char *)nth - nskb->head; 843 nskb->csum_offset = offsetof(struct tcphdr, check); 844 845 memset(&fl6, 0, sizeof(fl6)); 846 fl6.flowi6_proto = IPPROTO_TCP; 847 fl6.saddr = niph->saddr; 848 fl6.daddr = niph->daddr; 849 fl6.fl6_sport = nth->source; 850 fl6.fl6_dport = nth->dest; 851 security_skb_classify_flow((struct sk_buff *)skb, 852 flowi6_to_flowi_common(&fl6)); 853 err = nf_ip6_route(net, &dst, flowi6_to_flowi(&fl6), false); 854 if (err) { 855 goto free_nskb; 856 } 857 858 dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); 859 if (IS_ERR(dst)) 860 goto free_nskb; 861 862 skb_dst_set(nskb, dst); 863 864 if (nfct) { 865 nf_ct_set(nskb, (struct nf_conn *)nfct, ctinfo); 866 nf_conntrack_get(nfct); 867 } 868 869 ip6_local_out(net, nskb->sk, nskb); 870 return; 871 872 free_nskb: 873 kfree_skb(nskb); 874 } 875 876 void 877 synproxy_send_client_synack_ipv6(struct net *net, 878 const struct sk_buff *skb, 879 const struct tcphdr *th, 880 const struct synproxy_options *opts) 881 { 882 struct sk_buff *nskb; 883 struct ipv6hdr *iph, *niph; 884 struct tcphdr *nth; 885 unsigned int tcp_hdr_size; 886 u16 mss = opts->mss_encode; 887 888 iph = ipv6_hdr(skb); 889 890 tcp_hdr_size = sizeof(*nth) + synproxy_options_size(opts); 891 nskb = alloc_skb(sizeof(*niph) + tcp_hdr_size + MAX_TCP_HEADER, 892 GFP_ATOMIC); 893 if (!nskb) 894 return; 895 skb_reserve(nskb, MAX_TCP_HEADER); 896 897 niph = synproxy_build_ip_ipv6(net, nskb, &iph->daddr, &iph->saddr); 898 899 skb_reset_transport_header(nskb); 900 nth = skb_put(nskb, tcp_hdr_size); 901 nth->source = th->dest; 902 nth->dest = th->source; 903 nth->seq = htonl(nf_ipv6_cookie_init_sequence(iph, th, &mss)); 904 nth->ack_seq = htonl(ntohl(th->seq) + 1); 905 tcp_flag_word(nth) = TCP_FLAG_SYN | TCP_FLAG_ACK; 906 if (opts->options & NF_SYNPROXY_OPT_ECN) 907 tcp_flag_word(nth) |= TCP_FLAG_ECE; 908 nth->doff = tcp_hdr_size / 4; 909 nth->window = 0; 910 nth->check = 0; 911 nth->urg_ptr = 0; 912 913 synproxy_build_options(nth, opts); 914 915 synproxy_send_tcp_ipv6(net, skb, nskb, skb_nfct(skb), 916 IP_CT_ESTABLISHED_REPLY, niph, nth, 917 tcp_hdr_size); 918 } 919 EXPORT_SYMBOL_GPL(synproxy_send_client_synack_ipv6); 920 921 static void 922 synproxy_send_server_syn_ipv6(struct net *net, const struct sk_buff *skb, 923 const struct tcphdr *th, 924 const struct synproxy_options *opts, u32 recv_seq) 925 { 926 struct synproxy_net *snet = synproxy_pernet(net); 927 struct sk_buff *nskb; 928 struct ipv6hdr *iph, *niph; 929 struct tcphdr *nth; 930 unsigned int tcp_hdr_size; 931 932 iph = ipv6_hdr(skb); 933 934 tcp_hdr_size = sizeof(*nth) + synproxy_options_size(opts); 935 nskb = alloc_skb(sizeof(*niph) + tcp_hdr_size + MAX_TCP_HEADER, 936 GFP_ATOMIC); 937 if (!nskb) 938 return; 939 skb_reserve(nskb, MAX_TCP_HEADER); 940 941 niph = synproxy_build_ip_ipv6(net, nskb, &iph->saddr, &iph->daddr); 942 943 skb_reset_transport_header(nskb); 944 nth = skb_put(nskb, tcp_hdr_size); 945 nth->source = th->source; 946 nth->dest = th->dest; 947 nth->seq = htonl(recv_seq - 1); 948 /* ack_seq is used to relay our ISN to the synproxy hook to initialize 949 * sequence number translation once a connection tracking entry exists. 950 */ 951 nth->ack_seq = htonl(ntohl(th->ack_seq) - 1); 952 tcp_flag_word(nth) = TCP_FLAG_SYN; 953 if (opts->options & NF_SYNPROXY_OPT_ECN) 954 tcp_flag_word(nth) |= TCP_FLAG_ECE | TCP_FLAG_CWR; 955 nth->doff = tcp_hdr_size / 4; 956 nth->window = th->window; 957 nth->check = 0; 958 nth->urg_ptr = 0; 959 960 synproxy_build_options(nth, opts); 961 962 synproxy_send_tcp_ipv6(net, skb, nskb, &snet->tmpl->ct_general, 963 IP_CT_NEW, niph, nth, tcp_hdr_size); 964 } 965 966 static void 967 synproxy_send_server_ack_ipv6(struct net *net, const struct ip_ct_tcp *state, 968 const struct sk_buff *skb, 969 const struct tcphdr *th, 970 const struct synproxy_options *opts) 971 { 972 struct sk_buff *nskb; 973 struct ipv6hdr *iph, *niph; 974 struct tcphdr *nth; 975 unsigned int tcp_hdr_size; 976 977 iph = ipv6_hdr(skb); 978 979 tcp_hdr_size = sizeof(*nth) + synproxy_options_size(opts); 980 nskb = alloc_skb(sizeof(*niph) + tcp_hdr_size + MAX_TCP_HEADER, 981 GFP_ATOMIC); 982 if (!nskb) 983 return; 984 skb_reserve(nskb, MAX_TCP_HEADER); 985 986 niph = synproxy_build_ip_ipv6(net, nskb, &iph->daddr, &iph->saddr); 987 988 skb_reset_transport_header(nskb); 989 nth = skb_put(nskb, tcp_hdr_size); 990 nth->source = th->dest; 991 nth->dest = th->source; 992 nth->seq = htonl(ntohl(th->ack_seq)); 993 nth->ack_seq = htonl(ntohl(th->seq) + 1); 994 tcp_flag_word(nth) = TCP_FLAG_ACK; 995 nth->doff = tcp_hdr_size / 4; 996 nth->window = htons(state->seen[IP_CT_DIR_ORIGINAL].td_maxwin); 997 nth->check = 0; 998 nth->urg_ptr = 0; 999 1000 synproxy_build_options(nth, opts); 1001 1002 synproxy_send_tcp_ipv6(net, skb, nskb, NULL, 0, niph, nth, 1003 tcp_hdr_size); 1004 } 1005 1006 static void 1007 synproxy_send_client_ack_ipv6(struct net *net, const struct sk_buff *skb, 1008 const struct tcphdr *th, 1009 const struct synproxy_options *opts) 1010 { 1011 struct sk_buff *nskb; 1012 struct ipv6hdr *iph, *niph; 1013 struct tcphdr *nth; 1014 unsigned int tcp_hdr_size; 1015 1016 iph = ipv6_hdr(skb); 1017 1018 tcp_hdr_size = sizeof(*nth) + synproxy_options_size(opts); 1019 nskb = alloc_skb(sizeof(*niph) + tcp_hdr_size + MAX_TCP_HEADER, 1020 GFP_ATOMIC); 1021 if (!nskb) 1022 return; 1023 skb_reserve(nskb, MAX_TCP_HEADER); 1024 1025 niph = synproxy_build_ip_ipv6(net, nskb, &iph->saddr, &iph->daddr); 1026 1027 skb_reset_transport_header(nskb); 1028 nth = skb_put(nskb, tcp_hdr_size); 1029 nth->source = th->source; 1030 nth->dest = th->dest; 1031 nth->seq = htonl(ntohl(th->seq) + 1); 1032 nth->ack_seq = th->ack_seq; 1033 tcp_flag_word(nth) = TCP_FLAG_ACK; 1034 nth->doff = tcp_hdr_size / 4; 1035 nth->window = htons(ntohs(th->window) >> opts->wscale); 1036 nth->check = 0; 1037 nth->urg_ptr = 0; 1038 1039 synproxy_build_options(nth, opts); 1040 1041 synproxy_send_tcp_ipv6(net, skb, nskb, skb_nfct(skb), 1042 IP_CT_ESTABLISHED_REPLY, niph, nth, 1043 tcp_hdr_size); 1044 } 1045 1046 bool 1047 synproxy_recv_client_ack_ipv6(struct net *net, 1048 const struct sk_buff *skb, 1049 const struct tcphdr *th, 1050 struct synproxy_options *opts, u32 recv_seq) 1051 { 1052 struct synproxy_net *snet = synproxy_pernet(net); 1053 int mss; 1054 1055 mss = nf_cookie_v6_check(ipv6_hdr(skb), th, ntohl(th->ack_seq) - 1); 1056 if (mss == 0) { 1057 this_cpu_inc(snet->stats->cookie_invalid); 1058 return false; 1059 } 1060 1061 this_cpu_inc(snet->stats->cookie_valid); 1062 opts->mss_option = mss; 1063 opts->options |= NF_SYNPROXY_OPT_MSS; 1064 1065 if (opts->options & NF_SYNPROXY_OPT_TIMESTAMP) 1066 synproxy_check_timestamp_cookie(opts); 1067 1068 synproxy_send_server_syn_ipv6(net, skb, th, opts, recv_seq); 1069 return true; 1070 } 1071 EXPORT_SYMBOL_GPL(synproxy_recv_client_ack_ipv6); 1072 1073 unsigned int 1074 ipv6_synproxy_hook(void *priv, struct sk_buff *skb, 1075 const struct nf_hook_state *nhs) 1076 { 1077 struct net *net = nhs->net; 1078 struct synproxy_net *snet = synproxy_pernet(net); 1079 enum ip_conntrack_info ctinfo; 1080 struct nf_conn *ct; 1081 struct nf_conn_synproxy *synproxy; 1082 struct synproxy_options opts = {}; 1083 const struct ip_ct_tcp *state; 1084 struct tcphdr *th, _th; 1085 __be16 frag_off; 1086 u8 nexthdr; 1087 int thoff; 1088 1089 ct = nf_ct_get(skb, &ctinfo); 1090 if (!ct) 1091 return NF_ACCEPT; 1092 1093 synproxy = nfct_synproxy(ct); 1094 if (!synproxy) 1095 return NF_ACCEPT; 1096 1097 if (nf_is_loopback_packet(skb)) 1098 return NF_ACCEPT; 1099 1100 nexthdr = ipv6_hdr(skb)->nexthdr; 1101 thoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, 1102 &frag_off); 1103 if (thoff < 0 || nexthdr != IPPROTO_TCP) 1104 return NF_ACCEPT; 1105 1106 th = skb_header_pointer(skb, thoff, sizeof(_th), &_th); 1107 if (!th) 1108 return NF_DROP; 1109 1110 state = &ct->proto.tcp; 1111 switch (state->state) { 1112 case TCP_CONNTRACK_CLOSE: 1113 if (th->rst && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) { 1114 nf_ct_seqadj_init(ct, ctinfo, synproxy->isn - 1115 ntohl(th->seq) + 1); 1116 break; 1117 } 1118 1119 if (!th->syn || th->ack || 1120 CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) 1121 break; 1122 1123 /* Reopened connection - reset the sequence number and timestamp 1124 * adjustments, they will get initialized once the connection is 1125 * reestablished. 1126 */ 1127 nf_ct_seqadj_init(ct, ctinfo, 0); 1128 synproxy->tsoff = 0; 1129 this_cpu_inc(snet->stats->conn_reopened); 1130 fallthrough; 1131 case TCP_CONNTRACK_SYN_SENT: 1132 if (!synproxy_parse_options(skb, thoff, th, &opts)) 1133 return NF_DROP; 1134 1135 if (!th->syn && th->ack && 1136 CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) { 1137 /* Keep-Alives are sent with SEG.SEQ = SND.NXT-1, 1138 * therefore we need to add 1 to make the SYN sequence 1139 * number match the one of first SYN. 1140 */ 1141 if (synproxy_recv_client_ack_ipv6(net, skb, th, &opts, 1142 ntohl(th->seq) + 1)) { 1143 this_cpu_inc(snet->stats->cookie_retrans); 1144 consume_skb(skb); 1145 return NF_STOLEN; 1146 } else { 1147 return NF_DROP; 1148 } 1149 } 1150 1151 synproxy->isn = ntohl(th->ack_seq); 1152 if (opts.options & NF_SYNPROXY_OPT_TIMESTAMP) 1153 synproxy->its = opts.tsecr; 1154 1155 nf_conntrack_event_cache(IPCT_SYNPROXY, ct); 1156 break; 1157 case TCP_CONNTRACK_SYN_RECV: 1158 if (!th->syn || !th->ack) 1159 break; 1160 1161 if (!synproxy_parse_options(skb, thoff, th, &opts)) 1162 return NF_DROP; 1163 1164 if (opts.options & NF_SYNPROXY_OPT_TIMESTAMP) { 1165 synproxy->tsoff = opts.tsval - synproxy->its; 1166 nf_conntrack_event_cache(IPCT_SYNPROXY, ct); 1167 } 1168 1169 opts.options &= ~(NF_SYNPROXY_OPT_MSS | 1170 NF_SYNPROXY_OPT_WSCALE | 1171 NF_SYNPROXY_OPT_SACK_PERM); 1172 1173 swap(opts.tsval, opts.tsecr); 1174 synproxy_send_server_ack_ipv6(net, state, skb, th, &opts); 1175 1176 nf_ct_seqadj_init(ct, ctinfo, synproxy->isn - ntohl(th->seq)); 1177 nf_conntrack_event_cache(IPCT_SEQADJ, ct); 1178 1179 swap(opts.tsval, opts.tsecr); 1180 synproxy_send_client_ack_ipv6(net, skb, th, &opts); 1181 1182 consume_skb(skb); 1183 return NF_STOLEN; 1184 default: 1185 break; 1186 } 1187 1188 synproxy_tstamp_adjust(skb, thoff, th, ct, ctinfo, synproxy); 1189 return NF_ACCEPT; 1190 } 1191 EXPORT_SYMBOL_GPL(ipv6_synproxy_hook); 1192 1193 static const struct nf_hook_ops ipv6_synproxy_ops[] = { 1194 { 1195 .hook = ipv6_synproxy_hook, 1196 .pf = NFPROTO_IPV6, 1197 .hooknum = NF_INET_LOCAL_IN, 1198 .priority = NF_IP_PRI_CONNTRACK_CONFIRM - 1, 1199 }, 1200 { 1201 .hook = ipv6_synproxy_hook, 1202 .pf = NFPROTO_IPV6, 1203 .hooknum = NF_INET_POST_ROUTING, 1204 .priority = NF_IP_PRI_CONNTRACK_CONFIRM - 1, 1205 }, 1206 }; 1207 1208 int 1209 nf_synproxy_ipv6_init(struct synproxy_net *snet, struct net *net) 1210 { 1211 int err; 1212 1213 if (snet->hook_ref6 == 0) { 1214 err = nf_register_net_hooks(net, ipv6_synproxy_ops, 1215 ARRAY_SIZE(ipv6_synproxy_ops)); 1216 if (err) 1217 return err; 1218 } 1219 1220 snet->hook_ref6++; 1221 return 0; 1222 } 1223 EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_init); 1224 1225 void 1226 nf_synproxy_ipv6_fini(struct synproxy_net *snet, struct net *net) 1227 { 1228 snet->hook_ref6--; 1229 if (snet->hook_ref6 == 0) 1230 nf_unregister_net_hooks(net, ipv6_synproxy_ops, 1231 ARRAY_SIZE(ipv6_synproxy_ops)); 1232 } 1233 EXPORT_SYMBOL_GPL(nf_synproxy_ipv6_fini); 1234 #endif /* CONFIG_IPV6 */ 1235 1236 MODULE_LICENSE("GPL"); 1237 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 1238 MODULE_DESCRIPTION("nftables SYNPROXY expression support"); 1239