Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pi-hole v6.0 update not compatible with DNS widget #368

Open
ralphocdol opened this issue Feb 19, 2025 · 10 comments
Open

Pi-hole v6.0 update not compatible with DNS widget #368

ralphocdol opened this issue Feb 19, 2025 · 10 comments
Labels
bug report Something isn't working

Comments

@ralphocdol
Copy link
Contributor

Description

Seems like the API for Pi-hole v6 was rewritten on their Discourse.

And is accessible in our own instance at http://pi.hole/api/docs.

@ralphocdol ralphocdol added the bug report Something isn't working label Feb 19, 2025
@ralphocdol ralphocdol changed the title Pi-hole v6.0 updates breaks DNS widget Pi-hole v6.0 update not compatible with DNS widget Feb 19, 2025
@KallanX
Copy link

KallanX commented Feb 19, 2025

I believe the line to change is here

Based on the error I'm receiveing, it should look like this:
/api.php?summaryRaw&topItems&overTimeData10mins&auth=

Removing the "/admin".

Error:
"hint":"The API is hosted at pi.hole/api, not pi.hole/admin/api"

@ralphocdol
Copy link
Contributor Author

ralphocdol commented Feb 19, 2025

I believe the line to change is here

Removing the "/admin".

Unfortunately, it's a bit more complicated than that. As stated, the API was completely rewritten so we'd probably need a new one for v6. I did a quick check earlier

  1. The authentication method is different, on v5 we just need to provide a token that we can get somewhere in the Pi-hole settings. On v6, I couldn't find it, and it's called SID or Session ID. I manage to generate one with:
curl -k -X POST "https://pi.hole/api/auth" --data '{"password":"mypassword"}'

it should return with the sid you'd be needing for the rest(?) of the API requests. Example from docs:

{
  "session": {
       "valid": true,
       "totp": false,
       "sid": "vFA+EP4MQ5JJvJg+3Q2Jnw=",    <-- This thing
       "csrf": "Ux87YTIiMOf/GKCefVIOMw=",
       "validity": 300,
       "message": "correct password"
   }
}

(not sure about the validity yet as I was able to still use it after like 3 hours)

  1. For API requests, let's say GET https://pi.hole/api/stats/summary, a header X-FTL-SID with the value of SID generated above is needed.

@KallanX
Copy link

KallanX commented Feb 19, 2025

Yeah, you're right. I'm just looking more thoroughly into this now. The endpoint of /api/stats/summary works for the data we need to acquire.

(⎈ |lyra)keith@fedora:~ $ curl -s -k -X GET "http://192.168.1.225:8081/api/stats/summary?sid=<SID>=" | jq
{
  "queries": {
    "total": 19746,
    "blocked": 2468,
    "percent_blocked": 12.498733520507812,
    "unique_domains": 2006,
    "forwarded": 6671,
    "cached": 10362,
    "frequency": 0.46666666666666667,
    "types": {
      "A": 15123,
      "AAAA": 2863,
      "ANY": 0,
      "SRV": 0,
      "SOA": 0,
      "PTR": 270,
      "TXT": 0,
      "NAPTR": 0,
      "MX": 0,
      "DS": 0,
      "RRSIG": 0,
      "DNSKEY": 0,
      "NS": 0,
      "SVCB": 22,
      "HTTPS": 1468,
      "OTHER": 0
    },
    "status": {
      "UNKNOWN": 0,
      "GRAVITY": 2439,
      "FORWARDED": 6671,
      "CACHE": 4694,
      "REGEX": 0,
      "DENYLIST": 0,
      "EXTERNAL_BLOCKED_IP": 0,
      "EXTERNAL_BLOCKED_NULL": 0,
      "EXTERNAL_BLOCKED_NXRA": 0,
      "GRAVITY_CNAME": 3,
      "REGEX_CNAME": 0,
      "DENYLIST_CNAME": 0,
      "RETRIED": 0,
      "RETRIED_DNSSEC": 0,
      "IN_PROGRESS": 245,
      "DBBUSY": 0,
      "SPECIAL_DOMAIN": 26,
      "CACHE_STALE": 5668,
      "EXTERNAL_BLOCKED_EDE15": 0
    },
    "replies": {
      "UNKNOWN": 23,
      "NODATA": 1530,
      "NXDOMAIN": 262,
      "CNAME": 6228,
      "IP": 11542,
      "DOMAIN": 60,
      "RRNAME": 0,
      "SERVFAIL": 2,
      "REFUSED": 0,
      "NOTIMP": 0,
      "OTHER": 0,
      "DNSSEC": 0,
      "NONE": 0,
      "BLOB": 99
    }
  },
  "clients": {
    "active": 3,
    "total": 3
  },
  "gravity": {
    "domains_being_blocked": 125376,
    "last_update": 1739979593
  },
  "took": 0.000097513198852539062
}

I had to configure the app password and pass it (as you did) to the API to get the SID:

(⎈ |lyra)keith@fedora:~ $ curl -s -k -X POST "http://192.168.1.225:8081/api/auth" --data '{"password":"<PASSWORD>="}' | jq
{
  "session": {
    "valid": true,
    "totp": false,
    "sid": "<SID>",
    "csrf": "<CSRF>",
    "validity": 1800,
    "message": "app-password correct"
  },
  "took": 0.11159396171569824
}

The 'validity' value is interesting as I wonder how enforced that is. I'll continue to test to see.

Would you be open to possibly having the SID be reacquired with every API call via the widget? As in, a user will define the "app password" in the glance.yml and the logic will first call to the API to acquire a SID and then make the call to '/api/stats/summary' to get the necessary data?

Just thinking out loud. Sorry to be a bother.

@ralphocdol
Copy link
Contributor Author

ralphocdol commented Feb 19, 2025

I feel that would flood the Pi-hole with session records, but then again, I don't see any other way at the moment. Also, the validity record is there and I remember reading somewhere that it gets refreshed every time it is used.

Edit:
Well, you can check if the sid is still valid with GET /api/auth?sid= I believe, otherwise generate a new one.

@ralphocdol
Copy link
Contributor Author

Okay, just a moment ago I checked the dashboard at /admin/settings/api where I had one invalid session from testing with curl, I tried checking for validity with GET /api/auth?sid= and it was valid:true. Refreshing pihole dashboard and saw the validity was now updated and ticked.

Image

So this should work then?

@KallanX
Copy link

KallanX commented Feb 19, 2025

Yeah, I believe that's way forward here.

We can check the endpoint you mentioned to ensure our saved SID is still valid, if it's valid, gather data. If not, generate a new one.

(⎈ |lyra)keith@fedora:~ $ curl -s -k -X POST "http://192.168.1.225:8081/api/auth" --data '{"password":"<PWD>"}' | jq                                130
{
  "session": {
    "valid": true,
    "totp": false,
    "sid": "<SID>",
    "csrf": "<CSRF>",
    "validity": 1800,
    "message": "app-password correct"
  },
  "took": 0.1097404956817627
}
(⎈ |lyra)keith@fedora:~ $ curl -s -k -X GET "http://192.168.1.225:8081/api/auth?sid=<SID>" --data '{"password":"<PWD>"}' | jq
{
  "session": {
    "valid": true,
    "totp": false,
    "sid": "<SID>",
    "csrf": "<CSRF>",
    "validity": 1800,
    "message": "correct password"
  },
  "took": 0.000053167343139648438
}

@KallanX
Copy link

KallanX commented Feb 19, 2025

I believe I have a code solution for this but I am unable to push a branch. Is there a way I can be given that ability?

@ralphocdol
Copy link
Contributor Author

ralphocdol commented Feb 20, 2025

Pull Request.

  1. Fork the repo
  2. create a branch with the fix or new feature.
  3. Push it to your fork
  4. Create a pull request to this repo.

Do make sure that it is backwards compatible, I'd suggest service: pihole6 or something since this widget defaults to service: pihole

@ralphocdol
Copy link
Contributor Author

I just noticed with one of your curl, you don't need to pass --data on the GET one as it is not needed

(⎈ |lyra)keith@fedora:~ $ curl -s -k -X GET "http://192.168.1.225:8081/api/auth?sid=<SID>" --data '{"password":"<PWD>"}' | jq

And I believe you can skip this. I tried earlier while the session was not valid, using just /api/stats/summary and it got revalidated.

@KallanX
Copy link

KallanX commented Feb 20, 2025

PR is up

I kept the support within the already established service: pihole.

Let me know your thoughts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug report Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants