[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:
|
---|
| 319 | p 216-218 in cricket book
|
---|