| [2] | 1 | web frontend:
 | 
|---|
 | 2 | 
 | 
|---|
 | 3 | workflow:
 | 
|---|
 | 4 | 
 | 
|---|
 | 5 | log in, see domain list from current group
 | 
|---|
 | 6 | 
 | 
|---|
 | 7 | -> "current group" includes all subgroups?  (hairy SQL)
 | 
|---|
 | 8 | 
 | 
|---|
 | 9 | 
 | 
|---|
 | 10 | logic:
 | 
|---|
 | 11 | -> need to pass session ID on every call, otherwise we don't know who we are
 | 
|---|
 | 12 | -> should check ACLs on every call in case of changing permissions
 | 
|---|
 | 13 | -> should be able to store all webvar bits in the session
 | 
|---|
 | 14 | 
 | 
|---|
 | 15 | 
 | 
|---|
 | 16 | ooo! ooo!  what about "clone existing domain"?
 | 
|---|
 | 17 | 
 | 
|---|
 | 18 | 
 | 
|---|
| [81] | 19 | export for tinydns:  arbitrary record data is binary blob, decomposed by hex octets to octal codes
 | 
|---|
 | 20 | 
 | 
|---|
 | 21 | 
 | 
|---|
| [2] | 22 | components:
 | 
|---|
 | 23 | menu list (actions/sections)
 | 
|---|
 | 24 | domain list
 | 
|---|
 | 25 | group tree
 | 
|---|
 | 26 | user list
 | 
|---|
 | 27 | <various edit <entity> pages>
 | 
|---|
 | 28 | 
 | 
|---|
 | 29 | 
 | 
|---|
 | 30 | 
 | 
|---|
 | 31 | time tables:
 | 
|---|
 | 32 | 3600: 1h
 | 
|---|
 | 33 | 7200: 2h
 | 
|---|
 | 34 | 10800: 3h
 | 
|---|
 | 35 | 14400: 4h
 | 
|---|
 | 36 | 21600: 6h
 | 
|---|
 | 37 | 43200: 12h
 | 
|---|
 | 38 | 86400: 1d
 | 
|---|
 | 39 | 172800: 2d
 | 
|---|
 | 40 | 604800: 7d (1w)
 | 
|---|
 | 41 | 
 | 
|---|
 | 42 | valid records:
 | 
|---|
 | 43 | 
 | 
|---|
 | 44 | nb:  wildcards are supported for most types.  use with extreme caution!  (I don't plan on writing
 | 
|---|
 | 45 | tools that will create them.)
 | 
|---|
 | 46 | 
 | 
|---|
 | 47 | .fqdn:ip:x:ttl:timestamp:lo
 | 
|---|
 | 48 |  -> x.fqdn is a nameserver at ip, SOA sets x.fqdn as master with hostmaster@fqdn as contact
 | 
|---|
 | 49 |  -> if x contains a . that is used as the NS name
 | 
|---|
 | 50 | (Not much use for us)
 | 
|---|
 | 51 | 
 | 
|---|
 | 52 | Zfqdn:primary:contact:serial:refresh:retry:expire:minttl:recttl:(timestamp:lo)
 | 
|---|
 | 53 |  -> SOA for fqdn
 | 
|---|
 | 54 | 
 | 
|---|
 | 55 | &fqdn:ip:x:ttl:timestamp:lo
 | 
|---|
 | 56 |  -> x.fqdn is a nameserver
 | 
|---|
 | 57 |  -> if x contains a . that is used as the NS name
 | 
|---|
 | 58 |  -> ip may be omitted;  A record for fqdn->ip is created otherwise
 | 
|---|
 | 59 | 
 | 
|---|
 | 60 | =fqdn:ip:ttl:timestamp:lo
 | 
|---|
 | 61 |  -> A record and matching PTR record with fqdn and ip
 | 
|---|
 | 62 | 
 | 
|---|
 | 63 | +fqdn:ip:ttl:timestamp:lo
 | 
|---|
 | 64 |  -> A record
 | 
|---|
 | 65 | 
 | 
|---|
 | 66 | ^ptr:fqdn:ttl:timestamp:lo
 | 
|---|
 | 67 |  -> PTR record.  note ptr must be reverse-IP format ending in .in-addr.arpa
 | 
|---|
 | 68 | 
 | 
|---|
 | 69 | @fqdn:ip:x:dist:ttl:timestamp:lo
 | 
|---|
 | 70 |  -> MX.  Dist defaults to 0.
 | 
|---|
 | 71 |  -> ip may be omitted;  A record for fqdn->ip is created otherwise
 | 
|---|
 | 72 | 
 | 
|---|
 | 73 | -fqdn:ip:ttl:timestamp:lo
 | 
|---|
 | 74 |  -> ignored
 | 
|---|
 | 75 | 
 | 
|---|
 | 76 | 'fqdn:text:ttl:timestamp:lo
 | 
|---|
 | 77 |  -> TXT record
 | 
|---|
 | 78 |  -> octal-encode special characters in text as \nnn
 | 
|---|
 | 79 | 
 | 
|---|
 | 80 | Cfqdn:name:ttl:timestamp:lo
 | 
|---|
 | 81 |  -> CNAME for fqdn pointing to name
 | 
|---|
 | 82 | 
 | 
|---|
 | 83 | :fqdn:n:data:ttl:timestamp:lo
 | 
|---|
 | 84 |  -> Generic data, of type n (n is a 16-bit unsigned integer)
 | 
|---|
 | 85 |     17 is RP
 | 
|---|
 | 86 |     16 is TXT
 | 
|---|
 | 87 |     2 (NS), 5 (CNAME), 6 (SOA), 12 (PTR), 15 (MX) and 252 (AXFR) (WTF?) should not be used
 | 
|---|
 | 88 |  -> data must use octal escapes for : or nondisplayable characters.  axfr-get seems to escape all
 | 
|---|
 | 89 |     non-alphanumerics, therefore so will we.
 | 
|---|
 | 90 | 
 | 
|---|
 | 91 | two primary groups of data:
 | 
|---|
 | 92 | -> forward zones
 | 
|---|
 | 93 |   -> local master zones
 | 
|---|
 | 94 |   -> local slave zones
 | 
|---|
 | 95 | -> reverse zones
 | 
|---|
 | 96 | - note that it would be really nice to eliminate duplicated A records (+domain.com:ip:: plus =domain.com:ip::)
 | 
|---|
 | 97 | 
 | 
|---|
 | 98 | operations:
 | 
|---|
 | 99 | -> import zone data (BIND*, djbdns, vegadns-mysql)
 | 
|---|
 | 100 |   -> allow overwrite of existing SOA
 | 
|---|
 | 101 | -> export data (BIND*, djbdns)
 | 
|---|
 | 102 | -> add zone/domain
 | 
|---|
 | 103 |   -> as slave
 | 
|---|
 | 104 |   -> as master
 | 
|---|
 | 105 | -> delete zone/domain
 | 
|---|
 | 106 | -> add record to domain
 | 
|---|
 | 107 | -> remove record from domain
 | 
|---|
 | 108 | -> change record
 | 
|---|
 | 109 |   -> A record IP
 | 
|---|
 | 110 |   -> CNAME destination
 | 
|---|
 | 111 |   -> MX destination
 | 
|---|
 | 112 |   -> MX priority
 | 
|---|
 | 113 |   -> A <-> CNAME ?
 | 
|---|
 | 114 |   -> flag record as "primary" A record for an IP (means that PTR will set that name as rDNS)
 | 
|---|
 | 115 | -> force propagation (execute propagation script)
 | 
|---|
 | 116 | -> User ACL fiddling:
 | 
|---|
 | 117 |   -> take IPDB model, include groups/delegation/etc
 | 
|---|
 | 118 |     "admin" -> nominally full access to anything/everything
 | 
|---|
 | 119 |     "staff" -> general access to all domains, can create users and delegate domains to them
 | 
|---|
 | 120 |     "bulk hoster" -> customer with more than one domain, (can create users and delegate domains to them)?
 | 
|---|
 | 121 |     "user" -> customer with one domain
 | 
|---|
 | 122 |     
 | 
|---|
 | 123 | 
 | 
|---|
 | 124 | recommended SOA/TTL/etc times:
 | 
|---|
 | 125 | refresh 86400 (24h), retry 7200 (2h), expire 2592000 (30d), ttl 345600 (4d)
 | 
|---|
 | 126 | 
 | 
|---|
 | 127 | Qs re: new servers:
 | 
|---|
 | 128 | -> IPs for cache/authoritative?
 | 
|---|
 | 129 | 
 | 
|---|
 | 130 | 
 | 
|---|
 | 131 | flow of data:
 | 
|---|
 | 132 | user input -> database -> local "zone" data -> rsync/scp to slaves
 | 
|---|
 | 133 | 
 | 
|---|
 | 134 | don't use "domain ID" goop;  its only advantage is slightly lower disk use.  otherwise it's more
 | 
|---|
 | 135 | complicated, less traceable thru the DB manually
 | 
|---|
 | 136 | 
 | 
|---|
 | 137 | 
 | 
|---|
 | 138 | db structure (current)
 | 
|---|
 | 139 | 
 | 
|---|
 | 140 | domains:
 | 
|---|
 | 141 | | domain_id   | int(11)                   |      | MUL | NULL     | auto_increment |
 | 
|---|
 | 142 | | domain      | varchar(100)              |      |     |          |                |
 | 
|---|
 | 143 | | group_id    | int(11)                   | YES  |     | NULL     |                |
 | 
|---|
 | 144 | | description | varchar(255)              |      |     |          |                |
 | 
|---|
 | 145 | | status      | enum('active','inactive') |      |     | inactive |                |
 | 
|---|
 | 146 | 
 | 
|---|
 | 147 | records:
 | 
|---|
 | 148 | | domain_id   | int(11)      |      | MUL | 0       |                |
 | 
|---|
 | 149 | | record_id   | int(11)      |      | PRI | NULL    | auto_increment |
 | 
|---|
 | 150 | | host        | varchar(100) |      |     |         |                |
 | 
|---|
 | 151 | | type        | char(1)      | YES  |     | NULL    |                |
 | 
|---|
 | 152 | | val         | varchar(100) | YES  |     | NULL    |                |
 | 
|---|
 | 153 | | distance    | int(4)       | YES  |     | 0       |                |
 | 
|---|
 | 154 | | weight      | int(4)       | YES  |     | NULL    |                | - for SRV only
 | 
|---|
 | 155 | | port        | int(4)       | YES  |     | NULL    |                | - for SRV only
 | 
|---|
 | 156 | | ttl         | int(11)      |      |     | 86400   |                |
 | 
|---|
 | 157 | | description | varchar(255) |      |     |         |                |
 | 
|---|
 | 158 | 
 | 
|---|
 | 159 | default_records is a duplicate of records structurally
 | 
|---|
 | 160 | 
 | 
|---|
 | 161 | log:  (not sure how useful this really is, in this form...)
 | 
|---|
 | 162 | | domain_id | int(11)      |      |     | 0       |       |
 | 
|---|
 | 163 | | user_id   | int(11)      |      |     | 0       |       |
 | 
|---|
 | 164 | | group_id  | int(11)      |      |     | 0       |       |
 | 
|---|
 | 165 | | email     | varchar(60)  |      |     |         |       |
 | 
|---|
 | 166 | | name      | varchar(60)  |      |     |         |       |
 | 
|---|
 | 167 | | entry     | varchar(200) |      |     |         |       |
 | 
|---|
 | 168 | | time      | int(11)      |      |     | 0       |       |
 | 
|---|
 | 169 | 
 | 
|---|
 | 170 | db structure (proposed)
 | 
|---|
 | 171 | 
 | 
|---|
 | 172 | domains:
 | 
|---|
 | 173 | domain  char(128)       pk, indexed
 | 
|---|
 | 174 | group   char(32)        fk, indexed?
 | 
|---|
 | 175 | status  enum?
 | 
|---|
 | 176 | masterns char(64)
 | 
|---|
 | 177 | email   char(128)
 | 
|---|
 | 178 | serial  long int (needs 2^32 at least)
 | 
|---|
 | 179 | refresh long int        needs semi-sane default
 | 
|---|
 | 180 | retry   long int        needs semi-sane default
 | 
|---|
 | 181 | expire  long int        needs semi-sane default
 | 
|---|
 | 182 | minttl  long int        needs semi-sane default
 | 
|---|
 | 183 | ctime   timestamp
 | 
|---|
 | 184 | mtime   timestamp
 | 
|---|
 | 185 | 
 | 
|---|
 | 186 | records:
 | 
|---|
 | 187 | recid   serial
 | 
|---|
 | 188 | domain  char(128)       fk, indexed?
 | 
|---|
 | 189 | host    char(128)       pk, indexed
 | 
|---|
 | 190 | type    enum?
 | 
|---|
 | 191 | val     char(256)       to allow for 255-char TXT records
 | 
|---|
 | 192 | extra   char(10)        10 should be enough to express any needs for MX, SRV, or anything else...right?
 | 
|---|
 | 193 | ttl     long int
 | 
|---|
 | 194 | ctime   timestamp
 | 
|---|
 | 195 | mtime   timestamp
 | 
|---|
 | 196 | 
 | 
|---|
 | 197 | default records to be either database-coded as default values or coded in er, code.
 | 
|---|
 | 198 | -> hrm.
 | 
|---|
 | 199 |   database-level defaults are "recommended practice" according to the cricket book
 | 
|---|
 | 200 |   code-level defaults may be hardcoded (easy) or loaded from a config file (harder, but cleaner)
 | 
|---|
 | 201 |   all must be overrideable by a database-table-stored "local policy defaults" widget
 | 
|---|
 | 202 | 
 | 
|---|
 | 203 | add domain:
 | 
|---|
 | 204 |  -> need domain name
 | 
|---|
 | 205 |  -> IP/"company default" radio button pair, with some Javascript to change defaults for:
 | 
|---|
 | 206 |  -> radio buttons with sane defaults for standard hosts (www/mail/ftp/smtp)
 | 
|---|
 | 207 |    -> www CNAME @
 | 
|---|
 | 208 |    -> FTP CNAME @
 | 
|---|
 | 209 |    -> mail CNAME mail.company.com
 | 
|---|
 | 210 |    -> smtp CNAME smtp.company.com
 | 
|---|
 | 211 |    -> MX defaults to <mxlist>
 | 
|---|
 | 212 |    
 | 
|---|
 | 213 | +----------------------------------------------------------------+
 | 
|---|
 | 214 | | Domain: _________________________________                      |
 | 
|---|
 | 215 | | o Company hosting       o Slave zone        o Custom settings  |
 | 
|---|
 | 216 | +----------------------------------------------------------------+
 | 
|---|
 | 217 | 
 | 
|---|
 | 218 | add_domain($domain,$class)
 | 
|---|
 | 219 | update_domain($domain,$group,$status,[$contact,$primary,$serial,$ttl,$refresh,$retry,$expire,$minttl])
 | 
|---|
 | 220 | delete_domain($domain)
 | 
|---|
 | 221 | lock_domain($domain)  -hm..  lock/unlock may be admin-level "don't touch!" flags vs "active/inactive" flags
 | 
|---|
 | 222 | unlock_domain($domain)
 | 
|---|
 | 223 | add_record($domain,$host,$type,$value,$extra,$ttl)
 | 
|---|
 | 224 | update_record($id,$host,$type,$val,$extra,$ttl)
 | 
|---|
 | 225 | delete_record($id)
 | 
|---|
 | 226 | export_data($domain,$format) ->takes special <ALL> arg for all zones.  $format -> BIND or djb (implement DJB first)
 | 
|---|
 | 227 | update_nameservers()
 | 
|---|
 | 228 | 
 | 
|---|
| [39] | 229 | 
 | 
|---|
 | 230 | FFFF:FFFF:FFFF:FFFF : FFFF:FFFF:FFFF:FFFF
 | 
|---|
 | 231 | we get:
 | 
|---|
 | 232 |   <x>:<x>:FFFF:FFFF
 | 
|---|
 | 233 | we assign:
 | 
|---|
 | 234 |   <x>:<x>:<y>:<a>       (/64, nominally equivalent to current /32, logically)
 | 
|---|
 | 235 |   <x>:<x>:<y>:<b>FF     (/56, bitwise equivalent to current /24 relative to /32)
 | 
|---|
 | 236 |   <x>:<x>:<y>:FFFF      (/48, bitwise equivalent to current /16 relative to /24)
 | 
|---|
 | 237 |   
 | 
|---|
 | 238 | Allocations SHOULD leave space for growth
 | 
|---|
 | 239 | 
 | 
|---|
 | 240 | 
 | 
|---|
 | 241 | SELECT u.user_id, u.email, u.firstname, u.lastname, u.type, g.group_name
 | 
|---|
 | 242 |         "FROM users u ".
 | 
|---|
 | 243 |         "INNER JOIN groups g ON u.group_id=g.group_id ".
 | 
|---|
 | 244 |         ($offset eq 'all' ? '' : " LIMIT $perpage OFFSET ".$offset*$perpage)
 | 
|---|
 | 245 | 
 | 
|---|
 | 246 | 
 | 
|---|
 | 247 | SELECT g.group_id, g.group_name, g2.group_name, g.children, count(distinct(u.email)), count(distinct(d.domain))
 | 
|---|
 | 248 | FROM groups g
 | 
|---|
 | 249 | INNER JOIN groups g2 ON g2.group_id=g.parent_group_id
 | 
|---|
 | 250 | LEFT OUTER JOIN users u ON u.group_id=g.group_id
 | 
|---|
 | 251 | LEFT OUTER JOIN domains d ON d.group_id=g.group_id
 | 
|---|
 | 252 | GROUP BY g.group_id, g.group_name, g2.group_name, g.children
 | 
|---|
 | 253 | 
 | 
|---|
 | 254 | 
 | 
|---|
 | 255 | 
 | 
|---|
 | 256 |  record_id | group_id |                  host                  | type |           val           | distance | weight | port |  ttl  | description
 | 
|---|
 | 257 | -----------+----------+----------------------------------------+------+-------------------------+----------+--------+------+-------+-------------
 | 
|---|
 | 258 |          1 |        1 | ns1.example.com:hostmaster.DOMAIN      |    6 | 10800:3600:604800:10800 |        0 |      0 |    0 | 86400 |
 | 
|---|
 | 259 |         25 |        1 | DOMAIN                                 |    1 | 10.2.3.4                |        0 |      0 |    0 |  7200 |
 | 
|---|
 | 260 |          2 |        1 | DOMAIN                                 |   15 | mx1.example.com         |       10 |      0 |    0 |  7200 |
 | 
|---|
 | 261 |         26 |        1 | DOMAIN                                 |   15 | mx2.example.com         |       10 |      0 |    0 |  7200 |
 | 
|---|
 | 262 |         27 |        1 | DOMAIN                                 |    2 | ns2.example.com         |        0 |      0 |    0 |  7200 |
 | 
|---|
 | 263 |         22 |        1 | DOMAIN                                 |    2 | ns1.example.com         |        0 |      0 |    0 |  7200 |
 | 
|---|
 | 264 |         31 |        1 | www.DOMAIN                             |    5 | DOMAIN                  |        0 |      0 |    0 | 10800 |
 | 
|---|
 | 265 |         32 |        1 | DOMAIN                                 |   16 | "v=spf1 a mx -all"      |        0 |      0 |    0 | 10800 |
 | 
|---|
 | 266 |         17 |        1 | DOMAIN                                 |   33 | srv.example.com         |       15 |      2 |  325 |  7200 |
 | 
|---|
 | 267 | 
 | 
|---|
 | 268 | 
 | 
|---|
 | 269 | serial in domains table
 | 
|---|
 | 270 | 'manual' - date+inc
 | 
|---|
 | 271 | 'manual' - monotone
 | 
|---|
 | 272 | 'auto' - generated (TinyDNS only;  uses auto(date) for other exports)
 | 
|---|
 | 273 | 
 | 
|---|
| [81] | 274 | add enable/disable for individual records
 | 
|---|
| [39] | 275 | 
 | 
|---|
 | 276 | log_id?  domain_id?  group_id  user_id  action  detail timestamp
 | 
|---|
| [81] | 277 | 
 | 
|---|
 | 278 | 
 | 
|---|
 | 279 | 
 | 
|---|
 | 280 |        LOG_EMERG
 | 
|---|
 | 281 |               A panic condition.
 | 
|---|
 | 282 | 
 | 
|---|
 | 283 |        LOG_ALERT
 | 
|---|
 | 284 |               A condition that should be corrected immediately, such as a corrupted system database.
 | 
|---|
 | 285 | 
 | 
|---|
 | 286 |        LOG_CRIT
 | 
|---|
 | 287 |               Critical conditions, such as hard device errors.
 | 
|---|
 | 288 | 
 | 
|---|
 | 289 |        LOG_ERR
 | 
|---|
 | 290 |               Errors.
 | 
|---|
 | 291 | 
 | 
|---|
 | 292 |        LOG_WARNING
 | 
|---|
 | 293 | 
 | 
|---|
 | 294 |               Warning messages.
 | 
|---|
 | 295 | 
 | 
|---|
 | 296 |        LOG_NOTICE
 | 
|---|
 | 297 |               Conditions that are not error conditions, but that may require special handling.
 | 
|---|
 | 298 | 
 | 
|---|
 | 299 |        LOG_INFO
 | 
|---|
 | 300 |               Informational messages.
 | 
|---|
 | 301 | 
 | 
|---|
 | 302 |        LOG_DEBUG
 | 
|---|
 | 303 | #define LOG_EMERG       0       /* system is unusable */
 | 
|---|
 | 304 | #define LOG_ALERT       1       /* action must be taken immediately */
 | 
|---|
 | 305 | #define LOG_CRIT        2       /* critical conditions */
 | 
|---|
 | 306 | #define LOG_ERR         3       /* error conditions */
 | 
|---|
 | 307 | #define LOG_WARNING     4       /* warning conditions */
 | 
|---|
 | 308 | #define LOG_NOTICE      5       /* normal but significant condition */
 | 
|---|
 | 309 | #define LOG_INFO        6       /* informational */
 | 
|---|
 | 310 | #define LOG_DEBUG       7       /* debug-level messages */
 | 
|---|
| [269] | 311 | 
 | 
|---|
 | 312 | 
 | 
|---|
 | 313 | 
 | 
|---|
 | 314 | another web-UI for DNS record maintenance:
 | 
|---|
 | 315 | http://www.henriknordstrom.net/code/webdns/
 | 
|---|
 | 316 | 
 | 
|---|
 | 317 | 
 | 
|---|
 | 318 | sub-octet delegation for v4 nets:
 | 
|---|
| [305] | 319 | p 216-218 in cricket^Wgrasshopper book
 | 
|---|
 | 320 | 
 | 
|---|
 | 321 | Also see new draft spec, applies to both v4 and v6:
 | 
|---|
 | 322 | http://tools.ietf.org/html/draft-gersch-dnsop-revdns-cidr-01
 | 
|---|
 | 323 | 
 | 
|---|
 | 324 | new custom types "Forward delegation" and "Reverse delegation"?
 | 
|---|
 | 325 |  - forward creates NS records in parent for <sub>.parent
 | 
|---|
 | 326 |  - reverse creates NS records plus CNAMEs for sub-octet zones
 | 
|---|
 | 327 | -> would solve the conundrum of what to do with the unsightly CNAME
 | 
|---|
 | 328 |    records presented in the UI to indicate sub-octet zone delegation
 | 
|---|
| [713] | 329 | 
 | 
|---|
 | 330 | BIND reference for views/locations/split-horizon
 | 
|---|
 | 331 | https://kb.isc.org/article/AA-00851/0/Understanding-views-in-BIND-9-by-example.html
 | 
|---|
| [740] | 332 | 
 | 
|---|
 | 333 | HTML calendar widget?
 | 
|---|
 | 334 | http://www.cssflow.com/snippets/tag/date-picker  (paid)
 | 
|---|