Re: [DNSOP] I-D Action: draft-ietf-dnsop-rfc5011-security-considerations-08.txt

Michael StJohns <msj@nthpermutation.com> Fri, 15 December 2017 03:26 UTC

Return-Path: <msj@nthpermutation.com>
X-Original-To: dnsop@ietfa.amsl.com
Delivered-To: dnsop@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 102471279EB for <dnsop@ietfa.amsl.com>; Thu, 14 Dec 2017 19:26:20 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.6
X-Spam-Level:
X-Spam-Status: No, score=-2.6 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_LOW=-0.7] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=nthpermutation-com.20150623.gappssmtp.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 0XbEWxXY7eMa for <dnsop@ietfa.amsl.com>; Thu, 14 Dec 2017 19:26:17 -0800 (PST)
Received: from mail-qk0-x22c.google.com (mail-qk0-x22c.google.com [IPv6:2607:f8b0:400d:c09::22c]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id B657D1200F1 for <dnsop@ietf.org>; Thu, 14 Dec 2017 19:26:17 -0800 (PST)
Received: by mail-qk0-x22c.google.com with SMTP id r184so1175961qke.8 for <dnsop@ietf.org>; Thu, 14 Dec 2017 19:26:17 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nthpermutation-com.20150623.gappssmtp.com; s=20150623; h=subject:from:to:cc:references:message-id:date:user-agent :mime-version:in-reply-to:content-transfer-encoding:content-language; bh=Ow42v/UNQatumV1aMbnl03xUgxCF1pfBC1qNqrDkw9U=; b=ZTaaGErtEELhEg5H4rDLCUFLeqWQQGk75XUBsimfOu3nXL0lgufGYf80al2eNeFZQN uIYzOVp1m8wRCrbSlurgbk3YBUTUlLjYIG9AI6sp2mu896FyTSsomigNcNujVoir8am4 k8qjqtE5YL87E3E2jd7kQehdt61hGmeFz2o0BotwQOCF82kbptQ8tPmi5QaCKSoq4Qm4 8EaDfhmqqKHXRBrLHu/g6fTtjnT0NGboSdUVPmSS8SRsPlad2xlqZaJ0+x/p9jrpC3Pw vh2wMQkjKYMX4Ipi2iTOFEWXHx+qgVFHqesRJpm8L9ng4up2hd+kcZ9lCbOZAGhgB+Z4 f3Hw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:cc:references:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding :content-language; bh=Ow42v/UNQatumV1aMbnl03xUgxCF1pfBC1qNqrDkw9U=; b=k5SuXu8Z62Y3yOjBAfKZ1W4ef3PQlDheKhowTZY6idvonSQFFHFUNqYmjvPw4cskeQ bWD3sjBT0q2miPRQcZc3ttLZsT1VR3YM+rhrT59PzxZ5WuWOcmF9pTzMT7UkENTtTYx7 trdmqG5JG3ZjI9m1/fU95j9sQqcsRjZTQF05Ui0vMLyMdS0Nq9Gxu6se1IN9yMzkrwso wfTuqaZ96mAGzeOxzgFgjIVCRtZikxFBLtwsE2EKBzA6b+SQo3YUStUw4JXNVnCR37/E 8xpR/h0j5mVMyMfvikOKcMsE+mwHevjkfPE8VSGCsH+kgnLqrX5EG1vkcqUJrZrwMLtA 5Jdw==
X-Gm-Message-State: AKGB3mI8/n3/fTm6JHm48dIbByjcC6s7Qr3g82zb5RJ6yIS2CEWyJLFN kcsLl6tbC7nz815UMsV7czt+uYks
X-Google-Smtp-Source: ACJfBov3fDAPMfTbMGP4uas9Gg3fqrWnJCEyDeE15w/EDwphFtzHS+qd33TxPzSwnMKx04UGGTW2fA==
X-Received: by 10.55.164.132 with SMTP id n126mr18498941qke.85.1513308375891; Thu, 14 Dec 2017 19:26:15 -0800 (PST)
Received: from ?IPv6:2601:152:4400:720f::101f? ([2601:152:4400:720f::101f]) by smtp.gmail.com with ESMTPSA id z126sm3597259qka.70.2017.12.14.19.26.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 14 Dec 2017 19:26:14 -0800 (PST)
From: Michael StJohns <msj@nthpermutation.com>
To: Wes Hardaker <wjhns1@hardakers.net>
Cc: dnsop@ietf.org
References: <151199364931.4845.3034001091375154653@ietfa.amsl.com> <yblvahshg6z.fsf@wu.hardakers.net> <9c71768d-4807-3d0a-b4b1-0ac8d066fe9f@nthpermutation.com> <yblindiavlm.fsf@w7.hardakers.net> <6d239b9a-fd1e-46a3-c705-6851dd8ffe0a@nthpermutation.com> <ybl8te8kbaq.fsf@wu.hardakers.net> <142cad85-1e0e-b4c9-1561-ad590984739a@nthpermutation.com> <yblshcfhnai.fsf@wu.hardakers.net> <1ca3daed-d521-0fcd-d1e7-eef2b781707b@nthpermutation.com> <ybl8te7fyks.fsf@wu.hardakers.net> <26d61092-942a-16bc-e939-ed9400a17a29@nthpermutation.com>
Message-ID: <19e3ce86-c797-0e88-e192-e82b936be579@nthpermutation.com>
Date: Thu, 14 Dec 2017 22:26:13 -0500
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.5.0
MIME-Version: 1.0
In-Reply-To: <26d61092-942a-16bc-e939-ed9400a17a29@nthpermutation.com>
Content-Type: text/plain; charset="utf-8"; format="flowed"
Content-Transfer-Encoding: 8bit
Content-Language: en-US
Archived-At: <https://mailarchive.ietf.org/arch/msg/dnsop/nT71Xe-OJAtAdK1wr0fSmA3tfwI>
Subject: Re: [DNSOP] I-D Action: draft-ietf-dnsop-rfc5011-security-considerations-08.txt
X-BeenThere: dnsop@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: IETF DNSOP WG mailing list <dnsop.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/dnsop>, <mailto:dnsop-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/dnsop/>
List-Post: <mailto:dnsop@ietf.org>
List-Help: <mailto:dnsop-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/dnsop>, <mailto:dnsop-request@ietf.org?subject=subscribe>
X-List-Received-Date: Fri, 15 Dec 2017 03:26:20 -0000

Below is a java program I wrote to model this stuff.  In the table, SF2 
represents the number of clients that blew past twice the safety factor 
(for aR+aHD+aR), SF1 represents the number of clients that blew past the 
single safety factor.  OF is the number of clients using the 
activeRefreshOffset calculation that finished after the calculated 
interval (e.g. aR+aHD+aRO).  OF+s is the number of clients that finished 
after the activeRefreshOffset + safetyFactor (in the first table these 
are the same because of perfect responses).   In the second table, 
compare SF1 to OF+s - SF1 < OF+s suggesting that activeRefresh is a 
better choice that activeRefreshQuery for the third term of the 
equation.  You can try a lot of different combinations, but I haven't 
found any case where OF+s performs better that SF1.

The difference between lastStart and lAddHoldBegin represents the 
retransmits after the first query.  The differences between lAddHoldEnd 
and lFinalQuery represent retransmits after the last normal query before 
the end of the add hold down time until a valid answer was received 
after the addHoldDown time expired.

Feel free to twiddle with this.

In this table, almost 1/5th of each of the clients exceeds the 
activeRefreshOffset based calculation. Note that the safety factor 
doesn't come into play as this specifies a "0" query failure rate.
> java Test5011
> Original TTL? (enter dd:hh:mm:ss) 1:4:0:0
> New TTL? (enter dd:hh:mm:ss) 1:4:0:0
> RRSig expiration interval? (enter dd:hh:mm:ss) 7:0:0:0
>
> Orig TTL: 100800 seconds
> New TTL: 100800 seconds
> RRSig interval: 604800 seconds
> QueryInterval: 50400 seconds
> FastQuery: 8640 seconds
> AddHoldDown: 2592000 seconds
> ActiveRefreshOffset: 21600 seconds
> activeRefresh + addHoldDown + activeRefresh: 2692800
>
> Number of trials(-1 to exit) 10
> Number of clients(-1 to exit) 25000
> Failure rate [0 to .99999](-1 to exit) 0
> Calculated safety factor: 0 (0.000000)
> aR + aHD + aR + sF: 2692800
>
> Offset calc - aR + aHD + aRO: 2664000
> Offset plus safety: 2664000
>
> Trial  LastStart  lAddHoldBegin lAddHoldEnd  sOffset lFinalQuery SF2 
> SF1  OF  OF+s
> -----------------------------------------------------------------------------------
> 0      50394      50394         2671194       28800 2671194    0    
> 0    3459  3459
> 1      50399      50399         2671199       28800 2671199    0    
> 0    3576  3576
> 2      50399      50399         2671199       28800 2671199    0    
> 0    3540  3540
> 3      50399      50399         2671199       28800 2671199    0    
> 0    3508  3508
> 4      50399      50399         2671199       28800 2671199    0    
> 0    3610  3610
> 5      50399      50399         2671199       28800 2671199    0    
> 0    3544  3544
> 6      50398      50398         2671198       28800 2671198    0    
> 0    3546  3546
> 7      50399      50399         2671199       28800 2671199    0    
> 0    3611  3611
> 8      50398      50398         2671198       28800 2671198    0    
> 0    3579  3579
> 9      50398      50398         2671198       28800 2671198    0    
> 0    3517  3517





> $ !-2
> java Test5011
> Original TTL? (enter dd:hh:mm:ss) 1:0:0:0
> New TTL? (enter dd:hh:mm:ss) 1:0:0:0
> RRSig expiration interval? (enter dd:hh:mm:ss) 7:0:0:0
>
> Orig TTL: 86400 seconds
> New TTL: 86400 seconds
> RRSig interval: 604800 seconds
> QueryInterval: 43200 seconds
> FastQuery: 8640 seconds
> AddHoldDown: 2592000 seconds
> ActiveRefreshOffset: 0 seconds
> activeRefresh + addHoldDown + activeRefresh: 2678400
>
> Number of trials(-1 to exit) 10
> Number of clients(-1 to exit) 100000
> Failure rate [0 to .99999](-1 to exit) .25
> Calculated safety factor: 77760 (9.000000)
> aR + aHD + aR + sF: 2756160
>
> Offset calc - aR + aHD + aRO: 2635200
> Offset plus safety: 2712960
>
> Trial  LastStart  lAddHoldBegin lAddHoldEnd  sOffset lFinalQuery SF2 
> SF1  OF  OF+s
> -----------------------------------------------------------------------------------
> 0      43199      108405        2769525       0 2769525    0    1    
> 54772 31
> 1      43198      95039         2729831       0 2753326    0    0    
> 55168 26
> 2      43199      111816        2725266       0 2740462    0    0    
> 54697 44
> 3      43199      90159         2736412       0 2745052    0    0    
> 54882 31
> 4      43199      100917        2727795       0 2729947    0    0    
> 54869 33
> 5      43199      94115         2726425       0 2740485    0    0    
> 54978 23
> 6      43199      117523        2735443       0 2743990    0    0    
> 55306 27
> 7      43198      101417        2734743       0 2743383    0    0    
> 55006 29
> 8      43199      94634         2728554       0 2747760    0    0    
> 54943 36
> 9      43199      85218         2727853       0 2737153    0    0    
> 55070 33



import java.io.*;
import java.security.SecureRandom;

public class Test5011 {


   static  BufferedReader in = new BufferedReader(new InputStreamReader 
(System.in));



   public static void main (String[] args)
     throws Exception {

     int ttl = getResponse("Original TTL");
     int newTTL = getResponse ("New TTL");
     int rrsigExpire = getResponse ("RRSig expiration interval");
     System.out.println();

     boolean useSafetyFactor = true;


     System.out.printf ("Orig TTL: %d seconds%nNew TTL: %d 
seconds%nRRSig interval: %d seconds%n", ttl, newTTL, rrsigExpire);

     int thirtyDays = convertToSeconds ("30:0:0:0");
     int oneDay = convertToSeconds ("1:0:0:0");

     int oneHour = convertToSeconds ("0:1:0:0");

     int queryInterval = Math.max (oneHour, Math.min (thirtyDays/2, 
Math.min (ttl/2, rrsigExpire/2)));

     int fastQuery = Math.max (oneHour, Math.min (oneDay/10, Math.min 
(ttl/10, rrsigExpire/10)));
     int addHoldDown = Math.max (thirtyDays, newTTL);
     System.out.printf ("QueryInterval: %d seconds%nFastQuery: %d 
seconds%nAddHoldDown: %d seconds%n",
                queryInterval, fastQuery, addHoldDown);
     int activeRefreshOffset = addHoldDown % queryInterval;
     System.out.printf ("ActiveRefreshOffset: %d seconds%n", 
activeRefreshOffset);
     System.out.printf ("activeRefresh + addHoldDown + activeRefresh: 
%d%n%n",
                2*queryInterval + addHoldDown);

     int numberOfTrials = getInt ("Number of trials");
     int numberOfClients = getInt ("Number of clients");
     double queryFailureRate = getDouble ("Failure rate [0 to .99999]");

     double safetyFactorMultiple = Math.ceil((Math.log 
(numberOfClients)/Math.log(1.0/(queryFailureRate))));
     int origSafetyFactor = fastQuery * (int)safetyFactorMultiple;
     int safetyFactor = 2* fastQuery * (int)safetyFactorMultiple;
     int totalSafeInterval = safetyFactor + 2* queryInterval + addHoldDown;
     int totalOrigSafeInterval = origSafetyFactor + 2*queryInterval + 
addHoldDown;
     int offsetInterval = queryInterval + addHoldDown + activeRefreshOffset;
     int offsetSafeInterval = offsetInterval + origSafetyFactor;
     System.out.printf ("Calculated safety factor: %d (%.6f)%n", 
origSafetyFactor, safetyFactorMultiple);
     System.out.printf ("aR + aHD + aR + sF: %d%n%n", 
totalOrigSafeInterval);
     System.out.printf ("Offset calc - aR + aHD + aRO: %d%n", 
offsetInterval);
     System.out.printf ("Offset plus safety: %d%n%n", offsetSafeInterval);

     SecureRandom rnd = new SecureRandom();

     System.out.printf ("Trial  LastStart  lAddHoldBegin lAddHoldEnd  
sOffset  lFinalQuery SF2 SF1  OF  OF+s%n"+
"-----------------------------------------------------------------------------------%n");
     for (int j = 0; j < numberOfTrials; j++) {
     int latestStartOffset = 0;
     int latestAddHoldBegin = 0;
     int latestAddHoldEnd = 0;
     int latestFinalQuery = 0;
     int smallestOffsetAtEndOfAddHold = queryInterval;
     int numExceededSafety = 0;
     int numExceedOrigSafety = 0;
     int numExceedOffset = 0;
     int numExceedOffsetSafe = 0;


     for (int i = 0; i < numberOfClients; i++) {
     // each trial
       int startOffset = rnd.nextInt(queryInterval);
       latestStartOffset = (startOffset > latestStartOffset) ? 
startOffset : latestStartOffset;

       /* Roll the dice after each query and if we roll a number < the 
query failure rate, queue up a fast query and retry */

       while (rnd.nextDouble () < queryFailureRate) {
     startOffset += fastQuery;
       }

       latestAddHoldBegin = (startOffset > latestAddHoldBegin) ? 
startOffset : latestAddHoldBegin;


       // At beginning of add hold down period
       int trialAddHoldDown = 0;
       do {
     startOffset += queryInterval;
     trialAddHoldDown += queryInterval;
     // and retransmits
     while  (rnd.nextDouble () < queryFailureRate) {
       startOffset += fastQuery;
       trialAddHoldDown += fastQuery;
     }


       } while (trialAddHoldDown  < addHoldDown);
       latestAddHoldEnd = (startOffset > latestAddHoldEnd) ? startOffset 
: latestAddHoldEnd;
       int holddiff = trialAddHoldDown - addHoldDown;
       smallestOffsetAtEndOfAddHold = (holddiff < 
smallestOffsetAtEndOfAddHold) ?
     holddiff : smallestOffsetAtEndOfAddHold;


       // past the end of the addHoldDown, the previous last query above

       while (rnd.nextDouble () < queryFailureRate) {
     startOffset += fastQuery;
       }

       latestFinalQuery = (startOffset > latestFinalQuery) ? startOffset 
: latestFinalQuery;
       if (startOffset > totalSafeInterval)
     numExceededSafety++;
       if (startOffset >totalOrigSafeInterval)
     numExceedOrigSafety++;
       if (startOffset > offsetInterval)
     numExceedOffset++;
       if (startOffset > offsetSafeInterval)
     numExceedOffsetSafe++;

     }
     //System.out.printf ("Clients: %d%nLatestStartOffset 
%d%nLatestAddHoldBegin: %d%nLatestAddHoldEnd: %d%nSmallest Offset: 
%d%nLatestFinalQuery %d%n%n",

     System.out.printf ("%-7d%-11d%-14d%-14d%-9d%-11d%-5d%-5d%-5d %-5d%n",
                j,latestStartOffset, latestAddHoldBegin,
                 latestAddHoldEnd, smallestOffsetAtEndOfAddHold,
                latestFinalQuery, 
numExceededSafety,numExceedOrigSafety,numExceedOffset, numExceedOffsetSafe);
     }



   }

    public static double getDouble (String prompt)
     throws Exception {
     do {
       System.out.printf ("%s(-1 to exit) ", prompt);
       String resp = in.readLine();
       try {
     double val = Double.valueOf(resp);
     if (val < 0.0 || val >= 1.0)
       throw new NumberFormatException ("Number out of range");
     return val;
       } catch (NumberFormatException ex) {
     System.out.println (ex.getMessage());
       }
     } while (true);
   }


   public static int getInt (String prompt)
     throws Exception {
     do {
       System.out.printf ("%s(-1 to exit) ", prompt);
       String resp = in.readLine();
       try {
     int val = Integer.valueOf(resp);
     if (val < 0)
       System.exit(1);
     return val;
       } catch (NumberFormatException ex) {
     System.out.println (ex.getMessage());
       }
     } while (true);
   }

   // return interval in seconds
   public static int getResponse(String prompt)
     throws Exception{


     do {
       System.out.printf ("%s? (enter dd:hh:mm:ss) ", prompt);
       String resp = in.readLine();
       try {
     return convertToSeconds(resp);
       } catch (NumberFormatException ex) {
     System.out.println (ex.getMessage());
       }

     } while (true);
   }

   public static int convertToSeconds (String val)
     throws NumberFormatException {
     String[] comps = val.split(":");
     if (comps.length != 4) {
       throw new NumberFormatException ("Wrong number of components");
     }
     int[] conv = new int[4];

     for (int i = 0; i < 4; i++) {

       conv[i]  = Integer.valueOf(comps[i]);
       if (conv[i] < 0)
     throw new NumberFormatException("Less than zero");
     }


     if (conv[1] > 23 || conv[2] > 60 || conv[3] > 60) {
     throw new NumberFormatException ("Bad format - out of range for one 
or more elements");

     }
     return conv[3] + conv[2] * 60 + conv[1] * 3600 + conv[0] * 86400;

   }
}