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