Merge pull request #8 from peachcloud/talk-to-bind
Dynamic Configuration Of Bind Configurations Via Rocket API
This commit is contained in:
commit
0e1c662c17
|
@ -0,0 +1 @@
|
|||
DYN_ROOT_ZONE=
|
|
@ -1,2 +1,4 @@
|
|||
/target
|
||||
**/*.rs.bk
|
||||
ns_tests/*.key
|
||||
ns_tests/*
|
||||
|
|
|
@ -135,12 +135,48 @@ version = "1.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
||||
dependencies = [
|
||||
"block-padding",
|
||||
"byte-tools",
|
||||
"byteorder",
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
|
||||
dependencies = [
|
||||
"byte-tools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
|
||||
|
||||
[[package]]
|
||||
name = "byte-tools"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
|
@ -194,6 +230,16 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono-tz"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2554a3155fec064362507487171dcc4edc3df60cb10f3a1fb10ed8094822b120"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"parse-zoneinfo",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.3"
|
||||
|
@ -277,6 +323,17 @@ dependencies = [
|
|||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4feb231f0d4d6af81aed15928e58ecf5816aa62a2393e2c82f46973e92a9a278"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if 1.0.0",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "data-encoding"
|
||||
version = "2.3.2"
|
||||
|
@ -295,6 +352,12 @@ dependencies = [
|
|||
"syn 1.0.71",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deunicode"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690"
|
||||
|
||||
[[package]]
|
||||
name = "devise"
|
||||
version = "0.3.0"
|
||||
|
@ -325,12 +388,27 @@ dependencies = [
|
|||
"syn 1.0.71",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "discard"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
|
||||
|
||||
[[package]]
|
||||
name = "dotenv"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
|
||||
|
||||
[[package]]
|
||||
name = "dtoa"
|
||||
version = "0.4.8"
|
||||
|
@ -418,6 +496,12 @@ dependencies = [
|
|||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fake-simd"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
|
||||
[[package]]
|
||||
name = "figment"
|
||||
version = "0.10.5"
|
||||
|
@ -581,6 +665,15 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.2"
|
||||
|
@ -604,6 +697,30 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "globset"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"bstr",
|
||||
"fnv",
|
||||
"log",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "globwalk"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"ignore",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "0.3.3"
|
||||
|
@ -681,6 +798,12 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9"
|
||||
|
||||
[[package]]
|
||||
name = "humansize"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "1.3.0"
|
||||
|
@ -731,6 +854,24 @@ dependencies = [
|
|||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ignore"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b287fb45c60bb826a0dc68ff08742b9d88a2fea13d6e0c286b3172065aaf878c"
|
||||
dependencies = [
|
||||
"crossbeam-utils 0.8.4",
|
||||
"globset",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"memchr",
|
||||
"regex",
|
||||
"same-file",
|
||||
"thread_local",
|
||||
"walkdir",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.6.2"
|
||||
|
@ -856,6 +997,12 @@ dependencies = [
|
|||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maplit"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||
|
||||
[[package]]
|
||||
name = "matches"
|
||||
version = "0.1.8"
|
||||
|
@ -1085,6 +1232,12 @@ version = "1.7.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.9.0"
|
||||
|
@ -1136,19 +1289,31 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse-zoneinfo"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peach-dyndns-host"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap-log-flag",
|
||||
"clap-verbosity-flag",
|
||||
"dotenv",
|
||||
"futures 0.3.14",
|
||||
"log",
|
||||
"nest",
|
||||
"regex",
|
||||
"rocket",
|
||||
"rocket_contrib",
|
||||
"serde 1.0.125",
|
||||
"structopt",
|
||||
"tera",
|
||||
"tokio",
|
||||
"tokio-executor",
|
||||
"tokio-tcp",
|
||||
|
@ -1186,6 +1351,49 @@ version = "2.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
|
||||
dependencies = [
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2 1.0.26",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.71",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
|
||||
dependencies = [
|
||||
"maplit",
|
||||
"pest",
|
||||
"sha-1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.0.7"
|
||||
|
@ -1566,6 +1774,15 @@ version = "1.0.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.0"
|
||||
|
@ -1665,6 +1882,18 @@ dependencies = [
|
|||
"yaml-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"digest",
|
||||
"fake-simd",
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.6.0"
|
||||
|
@ -1686,6 +1915,15 @@ version = "0.4.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527"
|
||||
|
||||
[[package]]
|
||||
name = "slug"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373"
|
||||
dependencies = [
|
||||
"deunicode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "0.6.14"
|
||||
|
@ -1893,6 +2131,28 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tera"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b64b021b8d3ab1f59ceae9e6cd1c26c8e7ce0322a9ebfff6c0e22b3b66938935"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"chrono-tz",
|
||||
"globwalk",
|
||||
"humansize",
|
||||
"lazy_static",
|
||||
"percent-encoding",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
"rand 0.8.3",
|
||||
"regex",
|
||||
"serde 1.0.125",
|
||||
"serde_json",
|
||||
"slug",
|
||||
"unic-segment",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.2"
|
||||
|
@ -1931,6 +2191,15 @@ dependencies = [
|
|||
"syn 1.0.71",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.43"
|
||||
|
@ -2031,7 +2300,7 @@ version = "0.1.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"crossbeam-utils 0.7.2",
|
||||
"futures 0.1.31",
|
||||
]
|
||||
|
||||
|
@ -2063,7 +2332,7 @@ version = "0.1.12"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"crossbeam-utils 0.7.2",
|
||||
"futures 0.1.31",
|
||||
"lazy_static",
|
||||
"log",
|
||||
|
@ -2249,6 +2518,12 @@ dependencies = [
|
|||
"unchecked-index",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
|
||||
|
||||
[[package]]
|
||||
name = "ubyte"
|
||||
version = "0.10.1"
|
||||
|
@ -2258,6 +2533,12 @@ dependencies = [
|
|||
"serde 1.0.125",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
|
||||
|
||||
[[package]]
|
||||
name = "uncased"
|
||||
version = "0.9.6"
|
||||
|
@ -2274,6 +2555,56 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c"
|
||||
|
||||
[[package]]
|
||||
name = "unic-char-property"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221"
|
||||
dependencies = [
|
||||
"unic-char-range",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unic-char-range"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc"
|
||||
|
||||
[[package]]
|
||||
name = "unic-common"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
|
||||
|
||||
[[package]]
|
||||
name = "unic-segment"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23"
|
||||
dependencies = [
|
||||
"unic-ucd-segment",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unic-ucd-segment"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700"
|
||||
dependencies = [
|
||||
"unic-char-property",
|
||||
"unic-char-range",
|
||||
"unic-ucd-version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unic-ucd-version"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4"
|
||||
dependencies = [
|
||||
"unic-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.5"
|
||||
|
@ -2346,6 +2677,17 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi 0.3.9",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "want"
|
||||
version = "0.3.0"
|
||||
|
|
|
@ -20,3 +20,10 @@ trust-dns-client = "0.20.2"
|
|||
rocket = { git = "https://github.com/SergioBenitez/Rocket", branch = "master" }
|
||||
rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket", branch = "master" }
|
||||
serde = "1.0.125"
|
||||
dotenv = "0.15.0"
|
||||
tera = "1"
|
||||
regex = "1"
|
||||
|
||||
[[bin]]
|
||||
name = "main"
|
||||
path = "src/main.rs"
|
10
README.md
10
README.md
|
@ -1,6 +1,7 @@
|
|||
# peach-dyndns-host
|
||||
|
||||
a DNS server to host the names of guests with changing IP addresses
|
||||
a dynamic DNS server to host the names of guests with changing IP addresses. provides an http API
|
||||
for updating bind9 configurations.
|
||||
|
||||
_work in progress_
|
||||
|
||||
|
@ -15,7 +16,7 @@ cargo run -- -vvv # DEBUG log verbosity
|
|||
in another terminal
|
||||
|
||||
```shell
|
||||
dig @localhost -p 12323 test.dyn.peach.cloud
|
||||
nslookup blue.dyn.peachcloud.org ns.peachcloud.org
|
||||
```
|
||||
|
||||
or
|
||||
|
@ -23,3 +24,8 @@ or
|
|||
```shell
|
||||
curl http://localhost:3000
|
||||
```
|
||||
|
||||
|
||||
## testing
|
||||
|
||||
contains bash scripts for testing and debugging dynamic dns server behavior using nslookup
|
|
@ -0,0 +1,12 @@
|
|||
# For each subdomain,
|
||||
# - generate a new ddns key (tsig-keygen -a hmac-md5 {{subdomain}}.dyn.commoninternet.net) and append it to /etc/bind/dyn.commoninternet.net.keys
|
||||
# - add a zone section to /etc/bind/named.conf.local, associating the key with the subdomain
|
||||
# - add a minimal zone file to /var/lib/bind/subdomain.dyn.commoninternet.net
|
||||
# - reload bind and return the secret key to the client
|
||||
|
||||
SUBDOMAIN=$1
|
||||
BASE_DOMAIN=dyn.commoninternet.net
|
||||
FULL_DOMAIN="${SUBDOMAIN}.${BASE_DOMAIN}"
|
||||
echo "[generating zone for ${FULL_DOMAIN}]"
|
||||
|
||||
tsig-keygen -a hmac-md5 {{subdomain}}.dyn.commoninternet.net
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
|
||||
MYIP="1.1.1.9"
|
||||
|
||||
KEY=ddns.key
|
||||
NS=ns.commoninternet.net
|
||||
DOMAIN=test2.time.commoninternet.net.
|
||||
ZONE=time.commoninternet.net
|
||||
|
||||
nsupdate -k $KEY -v << EOF
|
||||
server $NS
|
||||
zone $ZONE
|
||||
update delete $DOMAIN A
|
||||
update add $DOMAIN 30 A $MYIP
|
||||
send
|
||||
EOF
|
|
@ -0,0 +1,37 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
ECHO=$(which echo)
|
||||
NSUPDATE=$(which nsupdate)
|
||||
|
||||
# Set the DNS entry you want to update, please notice the final dot.
|
||||
HOST="test.dyn.commoninternet.net"
|
||||
|
||||
# Set the key provided by your DNS administrator
|
||||
KEY="/etc/named/Kmydomain.com.+157+19553.key"
|
||||
|
||||
# Set the DNS server name or IP
|
||||
#SERVER="dyn.local:12323"
|
||||
SERVER="dyn.local 12323"
|
||||
|
||||
# Set the zone to modify, it can be any zone previous key has permissions to modify
|
||||
ZONE="dyn.commoninternet.net"
|
||||
|
||||
# Get your public IP address in the quickest and fanciest
|
||||
# way to if you have bind-tools installed
|
||||
#IP=`dig TXT +short o-o.myaddr.l.google.com @ns1.google.com | awk -F'"' '{ print $2}'`
|
||||
#OLDIP=`dig $HOST +short @8.8.8.8`
|
||||
IP="1.1.1.9"
|
||||
OLDIP="0.0.0.0"
|
||||
|
||||
if [ "$IP" != "$OLDIP" ];
|
||||
then
|
||||
$ECHO "server $SERVER" > /tmp/nsupdate
|
||||
$ECHO "debug yes" >> /tmp/nsupdate
|
||||
$ECHO "zone $ZONE" >> /tmp/nsupdate
|
||||
# $ECHO "update delete $HOST" >> /tmp/nsupdate
|
||||
$ECHO "update add $HOST 600 A $IP" >> /tmp/nsupdate
|
||||
$ECHO "send" >> /tmp/nsupdate
|
||||
else
|
||||
$ECHO "No update needed, exiting..."
|
||||
fi
|
||||
$NSUPDATE -k ${KEY} -v /tmp/nsupdate
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
|
||||
|
||||
Add the following to /etc/bind/named.conf.local:
|
||||
```
|
||||
key "ddns-key.dyn.commoninternet.net" {
|
||||
algorithm hmac-sha256;
|
||||
secret "yoursecrethere";
|
||||
};
|
||||
|
||||
zone "dyn.commoninternet.net" {
|
||||
type master;
|
||||
file "/var/lib/bind/dyn.commoninternet.net";
|
||||
update-policy {
|
||||
grant ddns-key.dyn.commoninternet.net subdomain dyn.commoninternet.net;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
For each subdomain,
|
||||
- generate a new ddns key (tsig-keygen -a hmac-md5 {{subdomain}}.dyn.commoninternet.net) and append it to /etc/bind/dyn.commoninternet.net.keys
|
||||
- add a zone section to named.conf.local, associating the key with the subdomain [B]
|
||||
- add a zone file to /var/lib/bind/subdomain.dyn.commoninternet.net [C]
|
||||
- reload bind and return the secret key to the client
|
||||
|
||||
Add the following to /var/lib/bind/{{subdomain}}.dyn.commoninternet.net: [C]
|
||||
```
|
||||
$ORIGIN .
|
||||
$TTL 30 ; 30 seconds
|
||||
{{subdomain}}.dyn.commoninternet.net IN SOA ns.commoninternet.net. root.commoninternet.net. (
|
||||
2016062801 ; serial
|
||||
3600 ; refresh (1 hour)
|
||||
600 ; retry (10 minutes)
|
||||
2600 ; expire (43 minutes 20 seconds)
|
||||
30 ; minimum (30 seconds)
|
||||
)
|
||||
NS ns.commoninternet.net.
|
||||
```
|
||||
|
||||
Append the following to /etc/bind/named.conf.local: [B]
|
||||
```
|
||||
zone "{{subdomain}}.dyn.commoninternet.net" {
|
||||
type master;
|
||||
file "/var/lib/bind/{{subdomain}}.dyn.commoninternet.net";
|
||||
update-policy {
|
||||
grant {{subdomain}}.dyn.commoninternet.net self {{subdomain}}.dyn.commoninternet.net;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
Questions:
|
||||
- an easy way to delete a subdomain?
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
|
||||
|
||||
Add the following to /etc/bind/named.conf.local:
|
||||
```
|
||||
key "ddns-key.dyn.commoninternet.net" {
|
||||
algorithm hmac-sha256;
|
||||
secret "yoursecrethere";
|
||||
};
|
||||
|
||||
zone "dyn.commoninternet.net" {
|
||||
type master;
|
||||
file "/var/lib/bind/dyn.commoninternet.net";
|
||||
update-policy {
|
||||
grant ddns-key.dyn.commoninternet.net subdomain dyn.commoninternet.net;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Add the following to /var/lib/bind/dyn.commoninternet.net:
|
||||
```
|
||||
$ORIGIN .
|
||||
$TTL 30 ; 30 seconds
|
||||
dyn.commoninternet.net IN SOA ns.commoninternet.net. root.commoninternet.net. (
|
||||
2016062801 ; serial
|
||||
3600 ; refresh (1 hour)
|
||||
600 ; retry (10 minutes)
|
||||
2600 ; expire (43 minutes 20 seconds)
|
||||
30 ; minimum (30 seconds)
|
||||
)
|
||||
NS ns.commoninternet.net.
|
||||
```
|
||||
Note that this file needs to be in /var/lib/bind for bind to have proper write permissions.
|
||||
|
||||
You can then add, delete and update subdomains using nsupdate.
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
|
||||
The following goes into `/etc/sudoers.d/bindctl` to enable peach-dyndns to reload bind.
|
||||
```
|
||||
#
|
||||
# Allow server to reload bind
|
||||
#
|
||||
|
||||
# User alias for bind-ctl which can reload bind
|
||||
User_Alias BIND_CTRL = peach-dynds
|
||||
|
||||
# Command alias for reboot and shutdown
|
||||
Cmnd_Alias RELOADBIND = /bin/reloadbind
|
||||
|
||||
# Allow BIND_CTRL users to execute RELOADBIND command without password
|
||||
BIND_CTRL ALL=(ALL) NOPASSWD: RELOADBIND
|
||||
```
|
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
cargo run --bin zone -- -vvv
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
|
||||
MYIP="1.1.1.55"
|
||||
|
||||
KEY=green.dyn.commoninternet.net.key
|
||||
NS=ns.commoninternet.net
|
||||
DOMAIN=gray.dyn.commoninternet.net.
|
||||
ZONE=gray.dyn.commoninternet.net
|
||||
|
||||
nsupdate -k $KEY -v << EOF
|
||||
server $NS
|
||||
zone $ZONE
|
||||
update delete $DOMAIN A
|
||||
update add $DOMAIN 30 A $MYIP
|
||||
send
|
||||
EOF
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
|
||||
MYIP="1.1.1.44"
|
||||
|
||||
KEY=green.dyn.commoninternet.net.key
|
||||
NS=ns.commoninternet.net
|
||||
DOMAIN=green.dyn.commoninternet.net.
|
||||
ZONE=green.dyn.commoninternet.net
|
||||
|
||||
nsupdate -k $KEY -v << EOF
|
||||
server $NS
|
||||
zone $ZONE
|
||||
update delete $DOMAIN A
|
||||
update add $DOMAIN 30 A $MYIP
|
||||
send
|
||||
EOF
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
|
||||
MYIP="1.1.1.11"
|
||||
|
||||
KEY=ddns.key
|
||||
NS=ns.commoninternet.net
|
||||
DOMAIN=orange.time.commoninternet.net.
|
||||
ZONE=time.commoninternet.net
|
||||
|
||||
nsupdate -k $KEY -v << EOF
|
||||
server $NS
|
||||
zone $ZONE
|
||||
update delete $DOMAIN A
|
||||
update add $DOMAIN 30 A $MYIP
|
||||
send
|
||||
EOF
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
// this regex is used to validate that domains are in the correct format
|
||||
// e.g. blue.dyn.peachcloud.org
|
||||
pub const DOMAIN_REGEX: &str = r"^.*\.dyn\.commoninternet\.net$";
|
95
src/dns.rs
95
src/dns.rs
|
@ -1,95 +0,0 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::time::Duration;
|
||||
use tokio::net::TcpListener;
|
||||
use tokio::net::UdpSocket;
|
||||
use trust_dns_client::rr::rdata::soa::SOA;
|
||||
use trust_dns_client::rr::{LowerName, Name, RData, Record, RecordSet, RecordType, RrKey};
|
||||
use trust_dns_server::authority::{Catalog, ZoneType};
|
||||
use trust_dns_server::server::ServerFuture;
|
||||
use trust_dns_server::store::in_memory::InMemoryAuthority;
|
||||
|
||||
static DEFAULT_TCP_REQUEST_TIMEOUT: u64 = 5;
|
||||
|
||||
pub async fn server() -> ServerFuture<Catalog> {
|
||||
info!("Trust-DNS {} starting", trust_dns_server::version());
|
||||
|
||||
let ip_addr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0));
|
||||
let listen_port: u16 = 12323;
|
||||
let tcp_request_timeout = Duration::from_secs(DEFAULT_TCP_REQUEST_TIMEOUT);
|
||||
|
||||
let sock_addr = SocketAddr::new(ip_addr, listen_port);
|
||||
let udp_socket = UdpSocket::bind(&sock_addr)
|
||||
.await
|
||||
.expect("could not bind udp socket");
|
||||
let tcp_listener = TcpListener::bind(&sock_addr)
|
||||
.await
|
||||
.expect("could not bind tcp listener");
|
||||
|
||||
let mut catalog: Catalog = Catalog::new();
|
||||
|
||||
let authority_name = Name::from_str("dyn.peach.cloud.").unwrap();
|
||||
let mut authority_records = BTreeMap::new();
|
||||
let authority_zone_type = ZoneType::Master;
|
||||
let authority_allow_axfr = false;
|
||||
|
||||
let soa_serial = 1;
|
||||
let soa_name = Name::from_str("dyn.peach.cloud.").unwrap();
|
||||
let soa_rdata = RData::SOA(SOA::new(
|
||||
Name::from_str("dyn.peach.cloud.").unwrap(), // mname
|
||||
Name::from_str("root.dyn.peach.cloud.").unwrap(), // rname
|
||||
soa_serial, // serial
|
||||
604800, // refresh
|
||||
86400, // retry
|
||||
2419200, // expire
|
||||
86400, // negtive cache ttl
|
||||
));
|
||||
let mut soa_record_set = RecordSet::new(&soa_name, RecordType::SOA, soa_serial);
|
||||
soa_record_set.add_rdata(soa_rdata);
|
||||
let soa_rr_key = RrKey::new(
|
||||
LowerName::new(&authority_name),
|
||||
soa_record_set.record_type(),
|
||||
);
|
||||
authority_records.insert(soa_rr_key, soa_record_set);
|
||||
|
||||
let mut authority = InMemoryAuthority::new(
|
||||
authority_name.clone(),
|
||||
authority_records,
|
||||
authority_zone_type,
|
||||
authority_allow_axfr,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
/*
|
||||
let ns_name = Name::from_str("dyn.peach.cloud.").unwrap();
|
||||
let ns_ttl = 60;
|
||||
let ns_rdata = RData::NS(Name::from_str("localhost.").unwrap());
|
||||
let ns_record = Record::from_rdata(ns_name, ns_ttl, ns_rdata);
|
||||
authority.upsert(ns_record, authority.serial());
|
||||
*/
|
||||
|
||||
let dyn_name = Name::from_str("test.dyn.peach.cloud.").unwrap();
|
||||
let dyn_ttl = 60;
|
||||
let dyn_rdata = RData::A(Ipv4Addr::new(1, 1, 1, 1));
|
||||
let dyn_record = Record::from_rdata(dyn_name, dyn_ttl, dyn_rdata);
|
||||
authority.upsert(dyn_record, authority.serial());
|
||||
|
||||
catalog.upsert(
|
||||
LowerName::new(&authority_name),
|
||||
Box::new(Arc::new(RwLock::new(authority))),
|
||||
);
|
||||
|
||||
let mut server = ServerFuture::new(catalog);
|
||||
|
||||
// load all the listeners
|
||||
info!("DNS server listening for UDP on {:?}", udp_socket);
|
||||
server.register_socket(udp_socket);
|
||||
|
||||
info!("DNS server listening for TCP on {:?}", tcp_listener);
|
||||
server.register_listener(tcp_listener, tcp_request_timeout);
|
||||
info!("awaiting DNS connections...");
|
||||
|
||||
server
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
use std::string::FromUtf8Error;
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum PeachDynError {
|
||||
GenerateTsigIoError(std::io::Error),
|
||||
GenerateTsigParseError(std::string::FromUtf8Error),
|
||||
DomainAlreadyExistsError(String),
|
||||
BindConfigurationError(String),
|
||||
InvalidDomainError(String)
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for PeachDynError {
|
||||
fn from(err: std::io::Error) -> PeachDynError {
|
||||
PeachDynError::GenerateTsigIoError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FromUtf8Error> for PeachDynError {
|
||||
fn from(err: std::string::FromUtf8Error) -> PeachDynError {
|
||||
PeachDynError::GenerateTsigParseError(err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Functions for generating bind9 configurations to enable dynamic dns for a subdomain via TSIG authentication
|
||||
* which is unique to that subdomain
|
||||
*/
|
||||
use std::fs::File;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Write;
|
||||
use std::process::Command;
|
||||
use tera::{Tera, Context};
|
||||
use crate::errors::PeachDynError;
|
||||
use crate::constants::DOMAIN_REGEX;
|
||||
|
||||
|
||||
/// function to generate the text of a TSIG key file
|
||||
pub fn generate_tsig_key(full_domain: &str) -> Result<String, PeachDynError> {
|
||||
let output = Command::new("/usr/sbin/tsig-keygen")
|
||||
.arg("-a")
|
||||
.arg("hmac-md5")
|
||||
.arg(full_domain)
|
||||
.output()?;
|
||||
let key_file_text = String::from_utf8(output.stdout)?;
|
||||
Ok(key_file_text)
|
||||
}
|
||||
|
||||
// function returns true if domain is of the format something.dyn.peachcloud.org
|
||||
pub fn validate_domain(domain: &str) -> bool {
|
||||
use regex::Regex;
|
||||
let re = Regex::new(DOMAIN_REGEX).unwrap();
|
||||
re.is_match(domain)
|
||||
}
|
||||
|
||||
/// function which helps us guarantee that a given domain is not already being used by bind
|
||||
/// it checks three places for the domain, and only returns true if it is not found in all three places
|
||||
/// - no already extant tsig key for the given domain
|
||||
/// - no zone file for the given domain in /var/lib/bind
|
||||
/// - no zone section for the given domain in named.conf.local
|
||||
pub fn check_domain_available(full_domain: &str) -> bool {
|
||||
let status1 = Command::new("/bin/grep")
|
||||
.arg(full_domain)
|
||||
.arg("/etc/bind/named.conf.local")
|
||||
.status().expect("error running grep on /etc/bind/named.conf.local");
|
||||
let code1 = status1.code().expect("error getting code from grep");
|
||||
let status2 = Command::new("/bin/grep")
|
||||
.arg(full_domain)
|
||||
.arg("/etc/bind/dyn.commoninternet.net.keys")
|
||||
.status().expect("error running grep on /etc/bind/dyn.commoninternet.net.keys");
|
||||
let code2 = status2.code().expect("error getting code from grep");
|
||||
let condition3 = std::path::Path::new(&format!("/var/lib/bind/{}", full_domain)).exists();
|
||||
|
||||
// domain is only available if domain does not exist in either named.conf.local or dyn.commoninternet.netkeys
|
||||
// and a file with that name is not found in /var/lib/bind/
|
||||
// grep returns a status code of 1 if lines are not found, which is why we check that the codes equal 1
|
||||
let domain_available = (code1 == 1) & (code2 == 1) & (!condition3);
|
||||
|
||||
// return
|
||||
domain_available
|
||||
|
||||
}
|
||||
|
||||
/// function which generates all necessary bind configuration to serve the given
|
||||
/// subdomain using dynamic DNS authenticated via a new TSIG key which is unique to that subdomain
|
||||
/// thus only the possessor of that key can use nsupdate to modify the records
|
||||
/// for that subodmain
|
||||
/// - generate a new ddns key (tsig-keygen -a hmac-md5 {{subdomain}}.dyn.commoninternet.net) and append it to /etc/bind/dyn.commoninternet.net.keys
|
||||
/// - add a zone section to /etc/bind/named.conf.local, associating the key with the subdomain
|
||||
/// - add a minimal zone file to /var/lib/bind/subdomain.dyn.commoninternet.net
|
||||
/// - reload bind and return the secret key to the client
|
||||
pub fn generate_zone(full_domain: &str) -> Result<String, PeachDynError> {
|
||||
|
||||
// first safety check domain is in correct format
|
||||
if !validate_domain(full_domain) {
|
||||
return Err(PeachDynError::InvalidDomainError(full_domain.to_string()));
|
||||
}
|
||||
|
||||
// safety check if the domain is available
|
||||
let is_available = check_domain_available(full_domain);
|
||||
if !is_available {
|
||||
return Err(PeachDynError::DomainAlreadyExistsError(full_domain.to_string()));
|
||||
}
|
||||
|
||||
// generate string with text for TSIG key file
|
||||
let key_file_text = generate_tsig_key(full_domain).expect("failed to generate tsig key");
|
||||
|
||||
// append key_file_text to /etc/bind/dyn.commoninternet.net.keys
|
||||
let key_file_path = "/etc/bind/dyn.commoninternet.net.keys";
|
||||
let mut file = OpenOptions::new().append(true).open(key_file_path)
|
||||
.expect(&format!("failed to open {}", key_file_path));
|
||||
if let Err(e) = writeln!(file, "{}", key_file_text) {
|
||||
error!("Couldn't write to file: {}", e);
|
||||
}
|
||||
|
||||
// append zone section to /etc/bind/named.conf.local
|
||||
let bind_conf_path = "/etc/bind/named.conf.local";
|
||||
let mut file = OpenOptions::new()
|
||||
.append(true)
|
||||
.open(bind_conf_path)
|
||||
.expect(&format!("failed to open {}", bind_conf_path));
|
||||
let zone_section_text = format!(
|
||||
"\
|
||||
zone \"{full_domain}\" {{
|
||||
type master;
|
||||
file \"/var/lib/bind/{full_domain}\";
|
||||
update-policy {{
|
||||
grant {full_domain} self {full_domain};
|
||||
}};
|
||||
}};
|
||||
",
|
||||
full_domain = full_domain
|
||||
);
|
||||
writeln!(file, "{}", zone_section_text).expect(&format!("Couldn't write to file: {}", bind_conf_path));
|
||||
|
||||
// use tera to render the zone file
|
||||
let tera = match Tera::new("templates/*.tera") {
|
||||
Ok(t) => t,
|
||||
Err(e) => {
|
||||
info!("Parsing error(s): {}", e);
|
||||
::std::process::exit(1);
|
||||
}
|
||||
};
|
||||
let mut context = Context::new();
|
||||
context.insert("full_domain", full_domain);
|
||||
let result = tera.render("zonefile.tera", &context).expect("error loading zonefile.tera");
|
||||
|
||||
// write new zone file to /var/lib/bind
|
||||
let zone_file_path = format!("/var/lib/bind/{}", full_domain);
|
||||
let mut file = File::create(&zone_file_path)
|
||||
.expect(&format!("failed to create {}", zone_file_path));
|
||||
writeln!(file, "{}", result).expect(&format!("Couldn't write to file: {}", zone_file_path));
|
||||
|
||||
// restart bind
|
||||
// we use the /etc/sudoers.d/bindctl to allow peach-dyndns user to restart bind as sudo without entering a password
|
||||
// using a binary at /bin/reloadbind which runs 'systemctl reload bind9'
|
||||
let status = Command::new("sudo")
|
||||
.arg("/bin/reloadbind")
|
||||
.status().expect("error restarting bind9");
|
||||
if !status.success() {
|
||||
return Err(PeachDynError::BindConfigurationError("There was an error in the bind configuration".to_string()));
|
||||
// TODO: for extra safety consider to revert bind configurations to whatever they were before
|
||||
}
|
||||
|
||||
// return success
|
||||
Ok(key_file_text)
|
||||
}
|
50
src/http.rs
50
src/http.rs
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* /register-user (sends an email verification to create a new account)
|
||||
* /verify (for clicking the link in the email)
|
||||
* /register-domain (add a new domain and get back the secret for subsequent updating)
|
||||
* /update-domain (update the IP for the domain, passing the associated secret)
|
||||
*
|
||||
*/
|
||||
use rocket_contrib::json::Json;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[get("/")]
|
||||
fn index() -> &'static str {
|
||||
"This is the peach-dyn-dns server."
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct RegisterDomainPost {
|
||||
domain: String,
|
||||
}
|
||||
|
||||
#[post("/register-domain", data = "<data>")]
|
||||
fn register_domain(data: Json<RegisterDomainPost>) -> &'static str {
|
||||
info!("++ post request to register new domain: {:?}", data);
|
||||
"New domain registered" // TODO: return secret
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct UpdateDomainPost {
|
||||
domain: String,
|
||||
secret: String,
|
||||
}
|
||||
|
||||
#[post("/update-domain", data = "<data>")]
|
||||
fn update_domain(data: Json<UpdateDomainPost>) -> &'static str {
|
||||
info!("++ post request to update domain: {:?}", data);
|
||||
"Updating domain" // TODO: validate, then do it
|
||||
}
|
||||
|
||||
pub async fn server() {
|
||||
|
||||
let rocket_result= rocket::build()
|
||||
.mount("/", routes![index, register_domain, update_domain])
|
||||
.launch()
|
||||
.await;
|
||||
|
||||
if let Err(err) = rocket_result {
|
||||
error!("++ error launching rocket server: {:?}", err);
|
||||
}
|
||||
}
|
34
src/main.rs
34
src/main.rs
|
@ -3,36 +3,24 @@
|
|||
#[macro_use]
|
||||
extern crate rocket;
|
||||
|
||||
use futures::try_join;
|
||||
use std::io;
|
||||
use tokio::task;
|
||||
use crate::routes::{index, register_domain, check_available};
|
||||
|
||||
mod cli;
|
||||
mod dns;
|
||||
mod http;
|
||||
mod routes;
|
||||
mod errors;
|
||||
mod constants;
|
||||
mod generate_zone;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let _args = cli::args().expect("error parsing args");
|
||||
|
||||
// create future for dns and http servers
|
||||
let dns_future = task::spawn(dns::server());
|
||||
let http_future = task::spawn(http::server());
|
||||
let rocket_result = rocket::build()
|
||||
.mount("/", routes![index, register_domain, check_available])
|
||||
.launch()
|
||||
.await;
|
||||
|
||||
// join futures
|
||||
let result = try_join!(dns_future, http_future);
|
||||
|
||||
match result {
|
||||
Err(e) => {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Interrupted,
|
||||
"Server stopping due to interruption",
|
||||
);
|
||||
error!("server failure: {}", e);
|
||||
}
|
||||
Ok(_val) => {
|
||||
info!("we're stopping for some unexpected reason");
|
||||
}
|
||||
if let Err(err) = rocket_result {
|
||||
error!("++ error launching rocket server: {:?}", err);
|
||||
}
|
||||
info!("we're stopping for some unexpected reason");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* LIST OF ROUTES
|
||||
* /domain/register (add a new domain and get back the TSIG key for subsequent updating with nsupdate)
|
||||
* /domain/check-available (check if given domain is available)
|
||||
* /user/register sends an email verification to create a new account) NOT IMPLEMENTED
|
||||
* /user/verify (for clicking the link in the email) NOT IMPLEMENTED
|
||||
*/
|
||||
use crate::generate_zone::{check_domain_available, generate_zone, validate_domain};
|
||||
use rocket_contrib::json::{Json, JsonValue};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[get("/")]
|
||||
pub fn index() -> &'static str {
|
||||
"This is the peach-dyndns server."
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct JsonResponse {
|
||||
pub status: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub data: Option<JsonValue>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub msg: Option<String>,
|
||||
}
|
||||
|
||||
// helper function to build a JsonResponse object
|
||||
pub fn build_json_response(
|
||||
status: String,
|
||||
data: Option<JsonValue>,
|
||||
msg: Option<String>,
|
||||
) -> JsonResponse {
|
||||
JsonResponse { status, data, msg }
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct RegisterDomainPost {
|
||||
domain: String,
|
||||
}
|
||||
|
||||
#[post("/domain/register", data = "<data>")]
|
||||
pub async fn register_domain(data: Json<RegisterDomainPost>) -> Json<JsonResponse> {
|
||||
info!("++ post request to register new domain: {:?}", data);
|
||||
// TODO: grab/create a mutex, so that only one rocket thread is calling register_domain at a time
|
||||
// check if its a valid domain
|
||||
if !validate_domain(&data.domain) {
|
||||
let status = "error".to_string();
|
||||
let msg = "domain is not in a valid format".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
} else {
|
||||
// check if the domain is available
|
||||
let is_domain_available = check_domain_available(&data.domain);
|
||||
if !is_domain_available {
|
||||
let status = "error".to_string();
|
||||
let msg = "can't register a domain that is already registered".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
} else {
|
||||
// generate configs for the zone
|
||||
let result = generate_zone(&data.domain);
|
||||
match result {
|
||||
Ok(key_file_text) => {
|
||||
let status = "success".to_string();
|
||||
let msg = key_file_text.to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
}
|
||||
Err(_err) => {
|
||||
let status = "error".to_string();
|
||||
let msg = "there was an error creating the zone file".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct CheckAvailableDomainPost {
|
||||
domain: String,
|
||||
}
|
||||
|
||||
// route which returns a msg of "true" if the domain is available and "false" if it is already taken
|
||||
#[post("/domain/check-available", data = "<data>")]
|
||||
pub async fn check_available(data: Json<CheckAvailableDomainPost>) -> Json<JsonResponse> {
|
||||
info!("post request to check if domain is available {:?}", data);
|
||||
if !validate_domain(&data.domain) {
|
||||
let status = "error".to_string();
|
||||
let msg = "domain is not in a valid format".to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
} else {
|
||||
let status = "success".to_string();
|
||||
let is_available = check_domain_available(&data.domain);
|
||||
let msg = is_available.to_string();
|
||||
Json(build_json_response(status, None, Some(msg)))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
$ORIGIN .
|
||||
$TTL 30 ; 30 seconds
|
||||
{{full_domain}} IN SOA ns.commoninternet.net. root.commoninternet.net. (
|
||||
2016062804 ; serial
|
||||
3600 ; refresh (1 hour)
|
||||
600 ; retry (10 minutes)
|
||||
2600 ; expire (43 minutes 20 seconds)
|
||||
30 ; minimum (30 seconds)
|
||||
)
|
||||
NS ns.commoninternet.net.
|
Loading…
Reference in New Issue