[GH-ISSUE #1732] Dynamic update no implemented #753

Open
opened 2026-03-16 00:08:27 +03:00 by kerem · 6 comments
Owner

Originally created by @xaneets on GitHub (Jul 6, 2022).
Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/1732

What is the question?
I can not deal with the dynamic update of dns. I send an update request to the server, it responds with NoImpl. I use sqlite with dnssec.
conf file for NS

[[zones]]
zone = "domain.org"
zone_type = "Primary"
allow_update = true
enable_dnssec = true
stores = { type = "sqlite", zone_file_path = "domain.org.zone",journal_file_path = "domain.org_dnsec_update.jrnl", allow_update = true }
[[zones.keys]]
key_path = "dnssec/rsa_2048.pem"
password = "123456"
algorithm = "RSASHA256"
is_zone_signing_key = true
 is_zone_update_auth = true

[[zones.keys]]
key_path = "dnssec/rsa_2048.pem"
password = "123456"
algorithm = "RSASHA512"
is_zone_signing_key = false
is_zone_update_auth = true

I am trying to update the zone in this way

let mut pem = File::open("/data/config/dnssec/key.pem").expect("could not find pem file");
let mut pem_buf = Vec::<u8>::new();
    pem.read_to_end(&mut pem_buf).expect("failed to read pem");
    let rsa = Rsa::private_key_from_pem(&pem_buf).expect("something wrong with key from pem");
    let key = KeyPair::from_rsa(rsa).unwrap();
    let sig0key = KEY::new(
        Default::default(),
        KeyUsage::Entity,
        Default::default(),
        Default::default(),
        Algorithm::RSASHA256,
        key.to_public_bytes().unwrap(),
    );

    let signer = SigSigner::sig0(sig0key, key, Name::from_str("update.domain.org").unwrap());

    let address = "127.0.0.1:53".parse().unwrap();
    let conn = UdpClientConnection::new(address).unwrap();
    let client = SyncClient::with_signer(conn, signer);
    let mut rrset = RecordSet::new(
        &Name::from_str("update.domain.org.").unwrap(),
        RecordType::A,
        199609203,
    );
    rrset.new_record(&RData::A(Ipv4Addr::new(127, 0, 0, 5)));
    client.append(rrset.clone(), Name::from_str("domain.org.").unwrap(), true);

Also I tried using SyncClient::new(conn) instead SyncClient::with_signer(conn, signer)

After that I get this response:

14:35:59 [DEBUG] (6) trust_dns_proto::xfer: enqueueing message: [Query { name: Name("domain.org."), query_type: SOA, query_class: IN }]
14:35:59 [DEBUG] (6) trust_dns_proto::op::message: finalizing message: Message { header: Header { id: 4111, message_type: Query, op_code: Update, authoritative: false, truncation: false, recursion_desired: false, recursion_available: false, authentic_data: false, checking_disabled: false, response_code: NoError, query_count: 0, answer_count: 0, name_server_count: 0, additional_count: 0 }, queries: [Query { name: Name("domain.org."), query_type: SOA, query_class: IN }], answers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: ANY, ttl: 0, rdata: None }], name_servers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: IN, ttl: 0, rdata: Some(A(127.0.0.5)) }], additionals: [], signature: [], edns: Some(Edns { rcode_high: 0, version: 0, dnssec_ok: false, max_payload: 1232, options: OPT { options: {} } }) }
14:35:59 [DEBUG] (6) trust_dns_client::rr::dnssec::signer: signing message: Message { header: Header { id: 4111, message_type: Query, op_code: Update, authoritative: false, truncation: false, recursion_desired: false, recursion_available: false, authentic_data: false, checking_disabled: false, response_code: NoError, query_count: 0, answer_count: 0, name_server_count: 0, additional_count: 0 }, queries: [Query { name: Name("domain.org."), query_type: SOA, query_class: IN }], answers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: ANY, ttl: 0, rdata: None }], name_servers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: IN, ttl: 0, rdata: Some(A(127.0.0.5)) }], additionals: [], signature: [], edns: Some(Edns { rcode_high: 0, version: 0, dnssec_ok: false, max_payload: 1232, options: OPT { options: {} } }) }
14:35:59 [DEBUG] (6) trust_dns_proto::udp::udp_stream: created socket successfully
14:35:59 [DEBUG] (2) trust_dns_server::server::server_future: received udp request from: 127.0.0.1:55653
14:35:59 [DEBUG] (2) trust_dns_server::server::server_future: request:4111 src:UDP://127.0.0.1#55653 type:QUERY dnssec:false UPDATE:domain.org.:SOA:IN qflags:
14:35:59 [DEBUG] (2) trust_dns_server::authority::catalog: update received: 4111
14:35:59 [DEBUG] (2) trust_dns_server::authority::catalog: searching authorities for: domain.org.
14:35:59 [DEBUG] (2) trust_dns_server::server::response_handler: response: 4111 response_code: Not Implemented
14:35:59 [INFO] request:4111 src:UDP://127.0.0.1#55653 UPDATE:domain.org.:SOA:IN qflags: response:NotImp rr:0/0/0 rflags:
14:35:59 [DEBUG] (6) trust_dns_proto::udp::udp_client_stream: received message id: 4111
Originally created by @xaneets on GitHub (Jul 6, 2022). Original GitHub issue: https://github.com/hickory-dns/hickory-dns/issues/1732 What is the question? I can not deal with the dynamic update of dns. I send an update request to the server, it responds with NoImpl. I use sqlite with dnssec. conf file for NS ``` [[zones]] zone = "domain.org" zone_type = "Primary" allow_update = true enable_dnssec = true stores = { type = "sqlite", zone_file_path = "domain.org.zone",journal_file_path = "domain.org_dnsec_update.jrnl", allow_update = true } [[zones.keys]] key_path = "dnssec/rsa_2048.pem" password = "123456" algorithm = "RSASHA256" is_zone_signing_key = true is_zone_update_auth = true [[zones.keys]] key_path = "dnssec/rsa_2048.pem" password = "123456" algorithm = "RSASHA512" is_zone_signing_key = false is_zone_update_auth = true ``` I am trying to update the zone in this way ``` let mut pem = File::open("/data/config/dnssec/key.pem").expect("could not find pem file"); let mut pem_buf = Vec::<u8>::new(); pem.read_to_end(&mut pem_buf).expect("failed to read pem"); let rsa = Rsa::private_key_from_pem(&pem_buf).expect("something wrong with key from pem"); let key = KeyPair::from_rsa(rsa).unwrap(); let sig0key = KEY::new( Default::default(), KeyUsage::Entity, Default::default(), Default::default(), Algorithm::RSASHA256, key.to_public_bytes().unwrap(), ); let signer = SigSigner::sig0(sig0key, key, Name::from_str("update.domain.org").unwrap()); let address = "127.0.0.1:53".parse().unwrap(); let conn = UdpClientConnection::new(address).unwrap(); let client = SyncClient::with_signer(conn, signer); let mut rrset = RecordSet::new( &Name::from_str("update.domain.org.").unwrap(), RecordType::A, 199609203, ); rrset.new_record(&RData::A(Ipv4Addr::new(127, 0, 0, 5))); client.append(rrset.clone(), Name::from_str("domain.org.").unwrap(), true); ``` Also I tried using ```SyncClient::new(conn)``` instead ```SyncClient::with_signer(conn, signer)``` After that I get this response: ``` 14:35:59 [DEBUG] (6) trust_dns_proto::xfer: enqueueing message: [Query { name: Name("domain.org."), query_type: SOA, query_class: IN }] 14:35:59 [DEBUG] (6) trust_dns_proto::op::message: finalizing message: Message { header: Header { id: 4111, message_type: Query, op_code: Update, authoritative: false, truncation: false, recursion_desired: false, recursion_available: false, authentic_data: false, checking_disabled: false, response_code: NoError, query_count: 0, answer_count: 0, name_server_count: 0, additional_count: 0 }, queries: [Query { name: Name("domain.org."), query_type: SOA, query_class: IN }], answers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: ANY, ttl: 0, rdata: None }], name_servers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: IN, ttl: 0, rdata: Some(A(127.0.0.5)) }], additionals: [], signature: [], edns: Some(Edns { rcode_high: 0, version: 0, dnssec_ok: false, max_payload: 1232, options: OPT { options: {} } }) } 14:35:59 [DEBUG] (6) trust_dns_client::rr::dnssec::signer: signing message: Message { header: Header { id: 4111, message_type: Query, op_code: Update, authoritative: false, truncation: false, recursion_desired: false, recursion_available: false, authentic_data: false, checking_disabled: false, response_code: NoError, query_count: 0, answer_count: 0, name_server_count: 0, additional_count: 0 }, queries: [Query { name: Name("domain.org."), query_type: SOA, query_class: IN }], answers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: ANY, ttl: 0, rdata: None }], name_servers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: IN, ttl: 0, rdata: Some(A(127.0.0.5)) }], additionals: [], signature: [], edns: Some(Edns { rcode_high: 0, version: 0, dnssec_ok: false, max_payload: 1232, options: OPT { options: {} } }) } 14:35:59 [DEBUG] (6) trust_dns_proto::udp::udp_stream: created socket successfully 14:35:59 [DEBUG] (2) trust_dns_server::server::server_future: received udp request from: 127.0.0.1:55653 14:35:59 [DEBUG] (2) trust_dns_server::server::server_future: request:4111 src:UDP://127.0.0.1#55653 type:QUERY dnssec:false UPDATE:domain.org.:SOA:IN qflags: 14:35:59 [DEBUG] (2) trust_dns_server::authority::catalog: update received: 4111 14:35:59 [DEBUG] (2) trust_dns_server::authority::catalog: searching authorities for: domain.org. 14:35:59 [DEBUG] (2) trust_dns_server::server::response_handler: response: 4111 response_code: Not Implemented 14:35:59 [INFO] request:4111 src:UDP://127.0.0.1#55653 UPDATE:domain.org.:SOA:IN qflags: response:NotImp rr:0/0/0 rflags: 14:35:59 [DEBUG] (6) trust_dns_proto::udp::udp_client_stream: received message id: 4111 ```
Author
Owner

@bluejekyll commented on GitHub (Jul 11, 2022):

What features are you using to build trust-dns? I think there are a few that are necessary for dynamic updates to work properly, specifically sqlite and one of the dnssec options.

<!-- gh-comment-id:1180628485 --> @bluejekyll commented on GitHub (Jul 11, 2022): What features are you using to build trust-dns? I think there are a few that are necessary for dynamic updates to work properly, specifically `sqlite` and one of the `dnssec` options.
Author
Owner

@xaneets commented on GitHub (Jul 11, 2022):

What features are you using to build trust-dns? I think there are a few that are necessary for dynamic updates to work properly, specifically sqlite and one of the dnssec options.

I solved part of the problem by specifying the default dnssec feature, but now the server returns Query Refused when trying to dynamically update

21:37:02 [DEBUG] (6) trust_dns_proto::xfer: enqueueing message: [Query { name: Name("domain.org."), query_type: SOA, query_class: IN }]
21:37:02 [DEBUG] (6) trust_dns_proto::op::message: finalizing message: Message { header: Header { id: 13201, message_type: Query, op_code: Update, authoritative: false, truncation: false, recursion_desired: false, recursion_available: false, authentic_data: false, checking_disabled: false, response_code: NoError, query_count: 0, answer_count: 0, name_server_count: 0, additional_count: 0 }, queries: [Query { name: Name("domain.org."), query_type: SOA, query_class: IN }], answers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: ANY, ttl: 0, rdata: None }], name_servers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: IN, ttl: 0, rdata: Some(A(127.0.0.5)) }], additionals: [], signature: [], edns: Some(Edns { rcode_high: 0, version: 0, dnssec_ok: false, max_payload: 1232, options: OPT { options: {} } }) }
21:37:02 [DEBUG] (6) trust_dns_client::rr::dnssec::signer: signing message: Message { header: Header { id: 13201, message_type: Query, op_code: Update, authoritative: false, truncation: false, recursion_desired: false, recursion_available: false, authentic_data: false, checking_disabled: false, response_code: NoError, query_count: 0, answer_count: 0, name_server_count: 0, additional_count: 0 }, queries: [Query { name: Name("domain.org."), query_type: SOA, query_class: IN }], answers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: ANY, ttl: 0, rdata: None }], name_servers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: IN, ttl: 0, rdata: Some(A(127.0.0.5)) }], additionals: [], signature: [], edns: Some(Edns { rcode_high: 0, version: 0, dnssec_ok: false, max_payload: 1232, options: OPT { options: {} } }) }
21:37:02 [DEBUG] (6) trust_dns_proto::udp::udp_stream: created socket successfully
21:37:02 [DEBUG] (2) trust_dns_server::server::server_future: received udp request from: 127.0.0.1:60759
21:37:02 [DEBUG] (2) trust_dns_server::server::server_future: request:13201 src:UDP://127.0.0.1#60759 type:QUERY dnssec:false UPDATE:domain.org.:SOA:IN qflags:
21:37:02 [DEBUG] (2) trust_dns_server::authority::catalog: update received: 13201
21:37:02 [DEBUG] (2) trust_dns_server::authority::catalog: searching authorities for: domain.org.
21:37:02 [DEBUG] (2) trust_dns_server::store::sqlite::authority: authorizing with: [Record { name_labels: Name("."), rr_type: SIG, dns_class: ANY, ttl: 0, rdata: Some(DNSSEC(SIG(SIG { type_covered: ZERO, algorithm: RSASHA256, num_labels: 0, original_ttl: 0, sig_expiration: 1657575722, sig_inception: 1657575422, key_tag: 61754, signer_name: Name("update.domain.org."), sig: [68, 213, 37, 141, 17, 222, 154, 80, 204, 221, 92, 171, 110, 1, 95, 141, 164, 156, 141, 88, 190, 57, 226, 227, 20, 60, 8, 55, 38, 251, 100, 190, 222, 222, 103, 31, 72, 106, 237, 77, 0, 81, 69, 79, 55, 194, 215, 130, 117, 49, 113, 133, 120, 213, 58, 31, 22, 86, 181, 126, 15, 250, 52, 117, 65, 3, 152, 102, 188, 53, 83, 177, 197, 185, 210, 83, 117, 75, 245, 247, 250, 11, 135, 221, 74, 2, 95, 123, 126, 55, 84, 24, 243, 243, 175, 215, 233, 135, 33, 233, 13, 116, 180, 73, 234, 10, 215, 239, 84, 179, 172, 16, 52, 206, 4, 186, 25, 70, 195, 185, 109, 76, 126, 3, 118, 219, 137, 187, 177, 204, 229, 57, 87, 193, 228, 32, 165, 69, 27, 71, 87, 247, 159, 41, 199, 164, 69, 37, 188, 110, 123, 96, 198, 151, 246, 43, 59, 150, 129, 240, 165, 129, 63, 81, 244, 143, 178, 88, 96, 141, 5, 77, 206, 187, 223, 86, 50, 122, 207, 223, 52, 128, 107, 57, 127, 74, 37, 31, 49, 152, 117, 24, 14, 140, 140, 31, 172, 25, 9, 66, 34, 153, 133, 67, 10, 182, 19, 50, 246, 250, 105, 39, 2, 28, 175, 97, 199, 145, 196, 1, 64, 78, 35, 242, 183, 52, 160, 42, 101, 216, 0, 85, 32, 159, 1, 53, 14, 189, 18, 3, 207, 16, 20, 153, 233, 173, 115, 249, 82, 6, 179, 186, 171, 58, 2, 30] }))) }]
21:37:02 [DEBUG] (2) trust_dns_server::server::response_handler: response: 13201 response_code: Query Refused
21:37:02 [INFO] request:13201 src:UDP://127.0.0.1#60759 UPDATE:domain.org.:SOA:IN qflags: response:Refused rr:0/0/1 rflags:
21:37:02 [DEBUG] (6) trust_dns_proto::udp::udp_client_stream: received message id: 13201
<!-- gh-comment-id:1180906107 --> @xaneets commented on GitHub (Jul 11, 2022): > What features are you using to build trust-dns? I think there are a few that are necessary for dynamic updates to work properly, specifically `sqlite` and one of the `dnssec` options. I solved part of the problem by specifying the default dnssec feature, but now the server returns ```Query Refused``` when trying to dynamically update ``` 21:37:02 [DEBUG] (6) trust_dns_proto::xfer: enqueueing message: [Query { name: Name("domain.org."), query_type: SOA, query_class: IN }] 21:37:02 [DEBUG] (6) trust_dns_proto::op::message: finalizing message: Message { header: Header { id: 13201, message_type: Query, op_code: Update, authoritative: false, truncation: false, recursion_desired: false, recursion_available: false, authentic_data: false, checking_disabled: false, response_code: NoError, query_count: 0, answer_count: 0, name_server_count: 0, additional_count: 0 }, queries: [Query { name: Name("domain.org."), query_type: SOA, query_class: IN }], answers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: ANY, ttl: 0, rdata: None }], name_servers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: IN, ttl: 0, rdata: Some(A(127.0.0.5)) }], additionals: [], signature: [], edns: Some(Edns { rcode_high: 0, version: 0, dnssec_ok: false, max_payload: 1232, options: OPT { options: {} } }) } 21:37:02 [DEBUG] (6) trust_dns_client::rr::dnssec::signer: signing message: Message { header: Header { id: 13201, message_type: Query, op_code: Update, authoritative: false, truncation: false, recursion_desired: false, recursion_available: false, authentic_data: false, checking_disabled: false, response_code: NoError, query_count: 0, answer_count: 0, name_server_count: 0, additional_count: 0 }, queries: [Query { name: Name("domain.org."), query_type: SOA, query_class: IN }], answers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: ANY, ttl: 0, rdata: None }], name_servers: [Record { name_labels: Name("update.domain.org."), rr_type: A, dns_class: IN, ttl: 0, rdata: Some(A(127.0.0.5)) }], additionals: [], signature: [], edns: Some(Edns { rcode_high: 0, version: 0, dnssec_ok: false, max_payload: 1232, options: OPT { options: {} } }) } 21:37:02 [DEBUG] (6) trust_dns_proto::udp::udp_stream: created socket successfully 21:37:02 [DEBUG] (2) trust_dns_server::server::server_future: received udp request from: 127.0.0.1:60759 21:37:02 [DEBUG] (2) trust_dns_server::server::server_future: request:13201 src:UDP://127.0.0.1#60759 type:QUERY dnssec:false UPDATE:domain.org.:SOA:IN qflags: 21:37:02 [DEBUG] (2) trust_dns_server::authority::catalog: update received: 13201 21:37:02 [DEBUG] (2) trust_dns_server::authority::catalog: searching authorities for: domain.org. 21:37:02 [DEBUG] (2) trust_dns_server::store::sqlite::authority: authorizing with: [Record { name_labels: Name("."), rr_type: SIG, dns_class: ANY, ttl: 0, rdata: Some(DNSSEC(SIG(SIG { type_covered: ZERO, algorithm: RSASHA256, num_labels: 0, original_ttl: 0, sig_expiration: 1657575722, sig_inception: 1657575422, key_tag: 61754, signer_name: Name("update.domain.org."), sig: [68, 213, 37, 141, 17, 222, 154, 80, 204, 221, 92, 171, 110, 1, 95, 141, 164, 156, 141, 88, 190, 57, 226, 227, 20, 60, 8, 55, 38, 251, 100, 190, 222, 222, 103, 31, 72, 106, 237, 77, 0, 81, 69, 79, 55, 194, 215, 130, 117, 49, 113, 133, 120, 213, 58, 31, 22, 86, 181, 126, 15, 250, 52, 117, 65, 3, 152, 102, 188, 53, 83, 177, 197, 185, 210, 83, 117, 75, 245, 247, 250, 11, 135, 221, 74, 2, 95, 123, 126, 55, 84, 24, 243, 243, 175, 215, 233, 135, 33, 233, 13, 116, 180, 73, 234, 10, 215, 239, 84, 179, 172, 16, 52, 206, 4, 186, 25, 70, 195, 185, 109, 76, 126, 3, 118, 219, 137, 187, 177, 204, 229, 57, 87, 193, 228, 32, 165, 69, 27, 71, 87, 247, 159, 41, 199, 164, 69, 37, 188, 110, 123, 96, 198, 151, 246, 43, 59, 150, 129, 240, 165, 129, 63, 81, 244, 143, 178, 88, 96, 141, 5, 77, 206, 187, 223, 86, 50, 122, 207, 223, 52, 128, 107, 57, 127, 74, 37, 31, 49, 152, 117, 24, 14, 140, 140, 31, 172, 25, 9, 66, 34, 153, 133, 67, 10, 182, 19, 50, 246, 250, 105, 39, 2, 28, 175, 97, 199, 145, 196, 1, 64, 78, 35, 242, 183, 52, 160, 42, 101, 216, 0, 85, 32, 159, 1, 53, 14, 189, 18, 3, 207, 16, 20, 153, 233, 173, 115, 249, 82, 6, 179, 186, 171, 58, 2, 30] }))) }] 21:37:02 [DEBUG] (2) trust_dns_server::server::response_handler: response: 13201 response_code: Query Refused 21:37:02 [INFO] request:13201 src:UDP://127.0.0.1#60759 UPDATE:domain.org.:SOA:IN qflags: response:Refused rr:0/0/1 rflags: 21:37:02 [DEBUG] (6) trust_dns_proto::udp::udp_client_stream: received message id: 13201 ```
Author
Owner

@bluejekyll commented on GitHub (Jul 11, 2022):

Try this specific dnssec feature: dnssec-ring

<!-- gh-comment-id:1180908934 --> @bluejekyll commented on GitHub (Jul 11, 2022): Try this specific dnssec feature: `dnssec-ring`
Author
Owner

@xaneets commented on GitHub (Jul 11, 2022):

Try this specific dnssec feature: dnssec-ring

After adding this feature, debug log has not changed.Server still responds with a Query Refused

<!-- gh-comment-id:1180919886 --> @xaneets commented on GitHub (Jul 11, 2022): > Try this specific dnssec feature: `dnssec-ring` After adding this feature, debug log has not changed.Server still responds with a ```Query Refused```
Author
Owner

@bluejekyll commented on GitHub (Jul 11, 2022):

There may be a bug here, but I'm not sure at the moment where that would be. This should work, and based on the your logs it looks like the client is signing the message properly. I would check the startup logs and make sure that the keys are being read properly during that phase.

I'll mark this as a bug, and we should build a full end-to-end test to verify the configuration. Today the tests around dynamic update are run as unit tests, not full integration tests, so there may be something amiss between those two.

<!-- gh-comment-id:1181098157 --> @bluejekyll commented on GitHub (Jul 11, 2022): There may be a bug here, but I'm not sure at the moment where that would be. This should work, and based on the your logs it looks like the client is signing the message properly. I would check the startup logs and make sure that the keys are being read properly during that phase. I'll mark this as a bug, and we should build a full end-to-end test to verify the configuration. Today the tests around dynamic update are run as unit tests, not full integration tests, so there may be something amiss between those two.
Author
Owner

@xaneets commented on GitHub (Aug 9, 2022):

Have there been any updates?

<!-- gh-comment-id:1209302281 --> @xaneets commented on GitHub (Aug 9, 2022): Have there been any updates?
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/hickory-dns#753
No description provided.