2

For example I have an array with this ips and want to create with my code an long spf record:

$array_ips = array();
$array_ips[] = "32.16.8.133"; 
$array_ips[] = "32.16.4.247";
$array_ips[] = "35.16.8.184";
$array_ips[] = "32.16.8.127";
$array_ips[] = "32.16.8.134";
$array_ips[] = "32.16.2.154";
$array_ips[] = "32.16.2.153";
$array_ips[] = "32.16.2.150";
$array_ips[] = "39.16.2.190";
$array_ips[] = "32.16.2.128";
$array_ips[] = "32.16.0.128";
$array_ips[] = "32.16.8.187";
$array_ips[] = "43.16.8.185";
$array_ips[] = "32.16.8.192";
$array_ips[] = "32.16.4.249";
$array_ips[] = "52.16.4.252";
$array_ips[] = "32.16.4.238";
$array_ips[] = "32.16.4.232";

$ips = implode(' ip4:', $array_ips);

echo "v=spf1 +a +mx".$ips." -all";

The spf record would be:

v=spf1 +a +mx ip4:32.16.8.133 ip4:32.16.4.247 ip4:32.16.8.184 ip4:32.16.8.127 ip4:32.16.8.134 ip4:32.16.2.154 ip4:32.16.2.153 ip4:32.16.2.150 ip4:32.16.2.190 ip4:32.16.2.128 ip4:32.16.0.128 ip4:32.16.8.187 ip4:32.16.8.185 ip4:32.16.8.192 ip4:32.16.4.249 ip4:32.16.4.252 ip4:32.16.4.238 ip4:32.16.4.232 -all 

Characters: 307

The Problem is, that an SPF only can be max. 255 characters long. No possibility to add such a long string in plesk or cpanel in txt dns record. I have heared that if could be possible to do it like this "v=spf1 .... first" "spf second string...".

But does it realy work? How to do it by generating it in my example above?

Mann87
  • 314
  • 1
  • 4
  • 14

4 Answers4

2

You can break it up into multiple include's..

"v=spf1 mx a include:iprange1.example.com include:iprange2.example.com -all"

Then under each include DNS you'll have

iprange1.example.com = "v=spf1 ip4:32.16.8.133 ... -all"
iprange2.example.com = "v=spf1 ip4:32.16.4.238 ... -all"

This will gave you a lot more room because you'll be able to include 8 includes along with your mx and a

Then each include can hold 16 ip4 addresses that will get your around 128 IP addresses that your can't CIDR.

Edit - iprange1 --> iprange2 on line 2 of 2nd code snippet

TheArchitecta
  • 273
  • 2
  • 17
Henry
  • 2,953
  • 2
  • 21
  • 34
1

You could do something like the below if your happy to allow a /24 subnet for a couple of IP's. You could even subnet it correctly if you fancied. It's cut down your list drastically anyways.

<?php

$array_ips = array();
$array_ips[] = "32.16.8.133"; 
$array_ips[] = "32.16.4.247";
$array_ips[] = "35.16.8.184";
$array_ips[] = "32.16.8.127";
$array_ips[] = "32.16.8.134";
$array_ips[] = "32.16.2.154";
$array_ips[] = "32.16.2.153";
$array_ips[] = "32.16.2.150";
$array_ips[] = "39.16.2.190";
$array_ips[] = "32.16.2.128";
$array_ips[] = "32.16.0.128";
$array_ips[] = "32.16.8.187";
$array_ips[] = "43.16.8.185";
$array_ips[] = "32.16.8.192";
$array_ips[] = "32.16.4.249";
$array_ips[] = "52.16.4.252";
$array_ips[] = "32.16.4.238";
$array_ips[] = "32.16.4.232";


$subnetArr = [];

foreach ($array_ips as $k=>$v ) {

    $i = strrpos($v, '.');
    $testSub = substr($v, 0, -(strlen($v) - $i));

    if (in_array("ip4:" . $testSub . ".1/24", $subnetArr)) {

        //Do something here or change condition

    } else {

        array_push($subnetArr,"ip4:" . $testSub . ".1/24");

    }
}


$ips = implode(' ', $subnetArr);
echo "v=spf1 +a +mx ".$ips." -all";

Output

v=spf1 +a +mx ip4:32.16.8.1/24 ip4:32.16.4.1/24 ip4:35.16.8.1/24 ip4:32.16.2.1/24 ip4:39.16.2.1/24 ip4:32.16.0.1/24 ip4:43.16.8.1/24 ip4:52.16.4.1/24 -all

Edit:

Just changed so it actually echo's SPF!

Kitson88
  • 2,889
  • 5
  • 22
  • 37
  • Thanks this solution is working. If it is the best solution I don't know. Because there is also the possibility to use someone that have an IP from range to use my domain for sending. – Mann87 Dec 08 '16 at 06:42
0

You'll need to do by sub-net. Use the standard IP4 sub-net notation:

"v=spf1 ip4:192.168.0.1/16 -all"

Allow any IP address between 192.168.0.1 and 192.168.255.255.

Robbie
  • 17,605
  • 4
  • 35
  • 72
  • But we don't have all ips. We get them randomly. So a add all variation is not an optimal solution or? – Mann87 Dec 07 '16 at 22:21
  • Yes - I wasn't sure from your example HOW random the IPs are, but you have no other solution but to allow some IPs you don;t control. The example in your question you could do `32.16.0.1/16` and cover them all, or you could add `32.16.2.1/24 32.16.4.1/24 32.16.8.1/24` to narrow it down. But you'll need some algorithm that covers all those you need. – Robbie Dec 07 '16 at 22:25
  • Otherwise, can you add multiple A records for the domain? I'm presuming not, but thought I'd mention as you have +a which means it'll check those. – Robbie Dec 07 '16 at 22:27
  • As defined in [RFC1035] sections 3.3.14 and 3.3, a single text DNS record (either TXT or SPF RR types) can be composed of more than one string. If a published record contains multiple strings, then the record MUST be treated as if those strings are concatenated together without adding spaces. For example: IN TXT "v=spf1 .... first" "second string..." but how to do it? – Mann87 Dec 07 '16 at 22:29
  • And...? Not sure what that's got to do with it? – Robbie Dec 07 '16 at 22:31
  • In [RFC1035] sections 3.3.14 and 3.3 stand that it must be possible to divide a long spf string in for example two parts in format: IN TXT "v=spf1 .... first" "second string..." – Mann87 Dec 07 '16 at 22:37
  • I have now tried it manually in plesk and it work to enter it. But how to gernerate it with the above example? – Mann87 Dec 07 '16 at 22:37
  • That's a different question! Use http://php.net/manual/en/function.chunk-split.php to split a string into 255 characters? – Robbie Dec 07 '16 at 22:39
-2

I have found the solution:

 echo "v=spf1 +a +mx ( "'.implode('" "',$array_ips).' " ) -all";

but the page i found it is not in enlish. (spaces are requierd and ())

http://www.nullpointer.at/keyword/spf/

Translated:

The TXT record is too long. Here, in this example, the TXT record was split into several lines. The syntax for this is: brace on (then in quotation marks "first part " next line in quotation marks "second part", etc., and finally parenthesis). Important: Do not forget the blanks within each section enclosed in quotation marks: "first part" "second part" is then composed to "first partsecond part".

JOUM
  • 239
  • 1
  • 3
  • your solution will not work echo will output v=spf1 +a +mx ( "32.16.8.133" "32.16.4.247" "32.16.8.184" "32.16.8.127" "32.16.8.134" "32.16.2.154" "32.16.2.153" "32.16.2.150" "32.16.2.190" "32.16.2.128" "32.16.0.128" "32.16.8.187" "32.16.8.185" "32.16.8.192" "32.16.4.249" "32.16.4.252" "32.16.4.238" "32.16.4.232 " ) -all – Mann87 Dec 07 '16 at 23:09
  • You have to spaces after an ip not `"32.16.8.133"` instead do this `"32.16.8.133 "` <-- note the space – JOUM Dec 09 '16 at 12:22