Block Services & Schedules¶
Ferrous DNS ships with a curated catalog of pre-defined services (advertising networks, social media platforms, analytics providers, etc.) that you can block with a single click — per group, with optional time-based scheduling.
How It Works¶
DNS query: graph.facebook.com
│
▼
1. Identify client group ──► "Kids"
│
▼
2. Check schedule state ──► is there an active schedule override?
│ ├─ BlockAll → BLOCK immediately
│ ├─ AllowAll → ALLOW immediately
│ └─ No override → continue
▼
3. Check blocked services ─► is "facebook" blocked for "Kids"?
│ ├─ YES → BLOCK (NXDOMAIN)
│ └─ NO → continue
▼
4. Normal blocking pipeline (blocklists, regex, CNAME cloaking…)
Block Services work on top of the standard Blocking & Filtering pipeline. They add managed domains from the service catalog to the block filter engine — no manual domain lists needed.
Service Catalog¶
The built-in catalog contains hundreds of services organized into categories. Each service maps to a set of domain rules that are maintained and updated automatically.
Categories¶
| Category | Examples | Use Case |
|---|---|---|
| Advertising | Google Ads, DoubleClick, Facebook Ads, Amazon Ads | Remove ads network-wide |
| Analytics & Tracking | Google Analytics, Mixpanel, Hotjar, Segment, Amplitude | Reduce tracking |
| Social Media | Facebook/Instagram, TikTok, Twitter/X, Snapchat, Pinterest, Reddit | Parental controls, productivity |
| Telemetry | Microsoft telemetry, Apple telemetry, Windows Update telemetry | Privacy |
| Adult Content | Adult content domains | Parental controls |
| Gambling | Online gambling platforms | Parental controls, compliance |
| Video Streaming | Netflix, YouTube, Disney+, Twitch | Bandwidth management, parental controls |
Viewing the Catalog¶
Blocking a Service¶
Quick Block (1-Click)¶
- Go to Services > Service Catalog
- Select the target Group from the dropdown (e.g. "Kids")
- Click the toggle next to the service you want to block
- The service is blocked immediately — no restart needed
Unblocking a Service¶
Listing Blocked Services¶
# All blocked services for a group
curl http://localhost:8080/api/services?group_id=2
# All blocked services globally
curl http://localhost:8080/api/services
Custom Services¶
If the built-in catalog doesn't cover a service you want to block, create a custom service with your own domain rules.
- Go to Services > Custom Services tab
- Click New Custom Service
- Fill in:
- Name: e.g. "Internal Analytics"
- Category: e.g. "Analytics & Tracking"
- Domains: one per line —
analytics.internal.com,metrics.internal.com
- Click Save
- The service now appears in the catalog and can be blocked per group like any built-in service
Custom vs. Blocklists
Use Custom Services when you want 1-click per-group control over a set of related domains. Use Blocklists when you have large external lists (thousands of domains) that apply globally. Custom Services are easier to manage for small, targeted blocks.
Per-Group Examples¶
Different groups can have completely independent blocking policies:
| Group | Blocked Services | Result |
|---|---|---|
| Kids | Social Media, Adult Content, Gambling, Video Streaming | No distractions, age-appropriate |
| Work | Advertising, Analytics & Tracking | Clean browsing, privacy |
| IoT | Telemetry, Analytics & Tracking, Advertising | Reduce phone-home traffic |
| Guest | Adult Content, Gambling | Basic content filtering |
| Default | (none) | No service blocking, only global blocklists |
Default Group
Clients not assigned to any group use the Default group. See Client Management for group setup and client assignment.
Schedule Profiles¶
Schedule Profiles let you control when blocking is active. Assign a schedule to a group and Ferrous DNS automatically enables or disables blocking based on time of day and day of week.
Concepts¶
| Concept | Description |
|---|---|
| Schedule Profile | A named set of time-based rules with a timezone (e.g. "Kids Weeknight") |
| Time Slot | A rule inside a profile: which days, start time, end time, and action |
| Action | block_all — block every DNS query; allow_all — bypass all blocking |
| Assignment | A profile is assigned to one or more groups |
Schedule Profile: "Kids Bedtime"
├── Timezone: America/Sao_Paulo
├── Slot 1: Mon–Thu, 21:00–23:59 → block_all
├── Slot 2: Fri–Sat, 23:00–23:59 → block_all
└── Assigned to: group "Kids" (id=2)
How Evaluation Works¶
The schedule evaluator runs every 60 seconds. For each group with an assigned profile:
- Determine the current day and time in the profile's timezone
- Check each time slot against the current day (bitmask) and time
- If a
block_allslot matches → setBlockAlloverride for the group - If an
allow_allslot matches (and noblock_all) → setAllowAlloverride - If no slot matches → remove override (normal blocking rules apply)
Conflict Resolution
If a block_all and allow_all slot overlap for the same time, block_all always wins. This prevents accidental bypasses.
Schedule Examples¶
Example 1: Kids Bedtime¶
Block all internet for children's devices on school nights:
- Go to Services > Schedule tab
- Click New Profile
- Name:
Kids Bedtime, Timezone:America/Sao_Paulo - Add time slots:
| Days | Start | End | Action |
|---|---|---|---|
| Mon, Tue, Wed, Thu | 21:00 | 23:59 | Block All |
| Fri, Sat | 23:00 | 23:59 | Block All |
- Assign to the Kids group
# 1. Create the profile
curl -X POST http://localhost:8080/api/schedule-profiles \
-H "Content-Type: application/json" \
-d '{
"name": "Kids Bedtime",
"timezone": "America/Sao_Paulo",
"comment": "Block internet on school nights"
}'
# Response: { "id": 1, ... }
# 2. Add slot: Mon–Thu 21:00–23:59 (days bitmask: 1+2+4+8 = 15)
curl -X POST http://localhost:8080/api/schedule-profiles/1/slots \
-H "Content-Type: application/json" \
-d '{
"days": 15,
"start_time": "21:00",
"end_time": "23:59",
"action": "block_all"
}'
# 3. Add slot: Fri–Sat 23:00–23:59 (days bitmask: 16+32 = 48)
curl -X POST http://localhost:8080/api/schedule-profiles/1/slots \
-H "Content-Type: application/json" \
-d '{
"days": 48,
"start_time": "23:00",
"end_time": "23:59",
"action": "block_all"
}'
# 4. Assign profile to Kids group (group_id = 2)
curl -X PUT http://localhost:8080/api/groups/2/schedule \
-H "Content-Type: application/json" \
-d '{"profile_id": 1}'
Example 2: Work Hours Focus¶
Block distracting services during work hours, allow everything outside:
Create a profile Work Focus with:
| Days | Start | End | Action |
|---|---|---|---|
| Mon–Fri | 09:00 | 18:00 | Block All |
Assign to the Work group.
# Create profile
curl -X POST http://localhost:8080/api/schedule-profiles \
-H "Content-Type: application/json" \
-d '{
"name": "Work Focus",
"timezone": "America/Sao_Paulo",
"comment": "Block distractions during work hours"
}'
# Add slot: Mon–Fri 09:00–18:00 (days: 1+2+4+8+16 = 31)
curl -X POST http://localhost:8080/api/schedule-profiles/2/slots \
-H "Content-Type: application/json" \
-d '{
"days": 31,
"start_time": "09:00",
"end_time": "18:00",
"action": "block_all"
}'
# Assign to Work group (group_id = 3)
curl -X PUT http://localhost:8080/api/groups/3/schedule \
-H "Content-Type: application/json" \
-d '{"profile_id": 2}'
Example 3: Weekend Allow Window¶
Children's devices are normally blocked, but allow internet on Saturday afternoons:
Create a profile Kids Weekend with:
| Days | Start | End | Action |
|---|---|---|---|
| Mon–Sun | 00:00 | 23:59 | Block All |
| Sat | 14:00 | 18:00 | Allow All |
Since block_all wins on conflicts, the allow window only applies during Saturday 14:00–18:00 when no block slot overlaps.
curl -X POST http://localhost:8080/api/schedule-profiles \
-H "Content-Type: application/json" \
-d '{
"name": "Kids Weekend",
"timezone": "America/Sao_Paulo",
"comment": "Block everything except Saturday afternoon"
}'
# Block all week (days: 127 = all days)
curl -X POST http://localhost:8080/api/schedule-profiles/3/slots \
-H "Content-Type: application/json" \
-d '{
"days": 127,
"start_time": "00:00",
"end_time": "13:59",
"action": "block_all"
}'
curl -X POST http://localhost:8080/api/schedule-profiles/3/slots \
-H "Content-Type: application/json" \
-d '{
"days": 127,
"start_time": "18:01",
"end_time": "23:59",
"action": "block_all"
}'
# Allow Saturday 14:00–18:00 (days: 32 = Saturday)
curl -X POST http://localhost:8080/api/schedule-profiles/3/slots \
-H "Content-Type: application/json" \
-d '{
"days": 32,
"start_time": "14:00",
"end_time": "18:00",
"action": "allow_all"
}'
Days Bitmask Reference¶
Time slots use a bitmask to represent days of the week. Combine values with addition:
| Day | Bit | Value |
|---|---|---|
| Monday | 0 | 1 |
| Tuesday | 1 | 2 |
| Wednesday | 2 | 4 |
| Thursday | 3 | 8 |
| Friday | 4 | 16 |
| Saturday | 5 | 32 |
| Sunday | 6 | 64 |
Common combinations:
| Days | Bitmask | Value |
|---|---|---|
| Mon–Fri (weekdays) | 0011111 | 31 |
| Sat–Sun (weekend) | 1100000 | 96 |
| Every day | 1111111 | 127 |
| Mon, Wed, Fri | 0010101 | 21 |
| Tue, Thu | 0001010 | 10 |
Managing Schedule Profiles¶
List All Profiles¶
Get Profile with Slots¶
Response:
{
"id": 1,
"name": "Kids Bedtime",
"timezone": "America/Sao_Paulo",
"comment": "Block internet on school nights",
"created_at": "2026-03-09T12:00:00Z",
"updated_at": "2026-03-09T12:00:00Z",
"slots": [
{
"id": 1,
"profile_id": 1,
"days": 15,
"start_time": "21:00",
"end_time": "23:59",
"action": "block_all",
"created_at": "2026-03-09T12:00:00Z"
},
{
"id": 2,
"profile_id": 1,
"days": 48,
"start_time": "23:00",
"end_time": "23:59",
"action": "block_all",
"created_at": "2026-03-09T12:00:00Z"
}
]
}
Update a Profile¶
curl -X PUT http://localhost:8080/api/schedule-profiles/1 \
-H "Content-Type: application/json" \
-d '{
"name": "Kids School Night",
"timezone": "America/Sao_Paulo",
"comment": "Updated: stricter schedule"
}'
Delete a Slot¶
Delete a Profile¶
Deleting a profile removes all its slots and group assignments:
Check Group Assignment¶
# What schedule is assigned to group 2?
curl http://localhost:8080/api/groups/2/schedule
# Remove schedule from group
curl -X DELETE http://localhost:8080/api/groups/2/schedule
API Reference¶
Block Services¶
| Method | Endpoint | Description |
|---|---|---|
GET | /api/services/catalog | List all services (built-in + custom) |
GET | /api/services/catalog/{id} | Get a single service definition |
GET | /api/services?group_id={id} | List blocked services for a group |
GET | /api/services | List all blocked services |
POST | /api/services | Block a service for a group |
DELETE | /api/services/{service_id}/groups/{group_id} | Unblock a service |
POST | /api/services/custom | Create a custom service |
Schedule Profiles¶
| Method | Endpoint | Description |
|---|---|---|
GET | /api/schedule-profiles | List all profiles |
POST | /api/schedule-profiles | Create a profile |
GET | /api/schedule-profiles/{id} | Get profile with time slots |
PUT | /api/schedule-profiles/{id} | Update a profile |
DELETE | /api/schedule-profiles/{id} | Delete profile (cascades) |
POST | /api/schedule-profiles/{id}/slots | Add a time slot |
DELETE | /api/schedule-profiles/{id}/slots/{slot_id} | Delete a time slot |
GET | /api/groups/{id}/schedule | Get assigned profile for group |
PUT | /api/groups/{id}/schedule | Assign profile to group |
DELETE | /api/groups/{id}/schedule | Remove schedule from group |