Есть правило iptables -t nat -A POSTROUTING -j SNAT --to-source 10.1.2.1-10.1.2.255 --persistent
В ядре 2.6.32 код отвечающий за то каким будет src_ip после ната выглядит так: net/ipv4/netfilter/nf_nat_core.c
/* Hashing source and destination IPs gives a fairly even
* spread in practice (if there are a small number of IPs
* involved, there usually aren't that many connections
* anyway). The consistency means that servers see the same
* client coming from the same IP (some Internet Banking sites
* like this), even across reboots. */
minip = ntohl(range->min_ip);
maxip = ntohl(range->max_ip);
j = jhash_2words((__force u32)tuple->src.u3.ip,
range->flags & IP_NAT_RANGE_PERSISTENT ?
0 : (__force u32)tuple->dst.u3.ip, 0);
j = ((u64)j * (maxip - minip + 1)) >> 32;
*var_ipp = htonl(minip + j);
для вычисления src_ip после ната использовал такую программу:
#include <stdio.h>
#include <stdint.h>
typedef uint8_t u8;
typedef uint32_t u32;
typedef uint64_t u64;
#define JHASH_INITVAL 0xdeadbeef
u32 parseIp(char *ipStr)
{
int i1, i2, i3, i4;
sscanf(ipStr, "%d.%d.%d.%d", &i1, &i2, &i3, &i4);
return (i1 << 24) + (i2 << 16) + (i3 << 8) + i4;
}
u32 rparseIp(char *ipStr)
{
int i1, i2, i3, i4;
sscanf(ipStr, "%d.%d.%d.%d", &i1, &i2, &i3, &i4);
return (i4 << 24) + (i3 << 16) + (i2 << 8) + i1;
}
static inline u32 rol32(u32 word, unsigned int shift)
{
return (word << shift) | (word >> (32 - shift));
}
static inline u32 jhash_2words(u32 a, u32 b, u32 c)
{
a += JHASH_INITVAL;
b += JHASH_INITVAL;
c ^= b; c -= rol32(b, 14);
a ^= c; a -= rol32(c, 11);
b ^= a; b -= rol32(a, 25);
c ^= b; c -= rol32(b, 16);
a ^= c; a -= rol32(c, 4);
b ^= a; b -= rol32(a, 14);
c ^= b; c -= rol32(b, 24);
return c;
}
int main(int argc, char *argv[]) {
if (argc < 4) {
printf("fail");
}
u32 minip, maxip, srcip, j, result;
minip = parseIp(argv[1]);
maxip = parseIp(argv[2]);
srcip = rparseIp(argv[3]);
j = jhash_2words(srcip, 0, 0);
j = ((u64)j * (maxip - minip + 1)) >> 32;
result = minip + j;
printf("%d.%d.%d.%d\n", (u8)(result >> 24), (u8)(result >> 16), (u8)(result >> 8), (u8)result);
return 0;
}
на вход которой передавал начало диапазона, конец диапазона, приватный ip. На выходе получался публичный адрес который будет после ната. для новых ядер она выдаёт не верный адрес, так как код ядра изменился и выглядит теперь так net/netfilter/nf_nat_core.c:
/* Hashing source and destination IPs gives a fairly even
* spread in practice (if there are a small number of IPs
* involved, there usually aren't that many connections
* anyway). The consistency means that servers see the same
* client coming from the same IP (some Internet Banking sites
* like this), even across reboots.
*/
j = jhash2((u32 *)&tuple->src.u3, sizeof(tuple->src.u3) / sizeof(u32),
range->flags & NF_NAT_RANGE_PERSISTENT ?
0 : (__force u32)tuple->dst.u3.all[max] ^ zone);
full_range = false;
for (i = 0; i <= max; i++) {
/* If first bytes of the address are at the maximum, use the
* distance. Otherwise use the full range.
*/
if (!full_range) {
minip = ntohl((__force __be32)range->min_addr.all[i]);
maxip = ntohl((__force __be32)range->max_addr.all[i]);
dist = maxip - minip + 1;
} else {
minip = 0;
dist = ~0;
}
var_ipp->all[i] = (__force __u32)
htonl(minip + (((u64)j * dist) >> 32));
if (var_ipp->all[i] != range->max_addr.all[i])
full_range = true;
if (!(range->flags & NF_NAT_RANGE_PERSISTENT))
j ^= (__force u32)tuple->dst.u3.all[i];
}
раньше, как я понял, хеш вычислялся на основе ip адреса (__force u32)tuple->src.u3.ip теперь он вычисляется из (u32 *)&tuple->src.u3 Что это такое я понять не могу. Исходники 2.6.32 и 3.13 скачал, сравнивал, но так и не смог разобраться что к чему. Прошу помочь, разработчиком на С не являюсь.