macfw 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
macfw-0.1.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 tudoujun
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
macfw-0.1.1/PKG-INFO ADDED
@@ -0,0 +1,386 @@
1
+ Metadata-Version: 2.4
2
+ Name: macfw
3
+ Version: 0.1.1
4
+ Summary: A small pf-based firewall manager for macOS with a ufw-like CLI
5
+ Author: tudoujun
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/tudoujunha/macfw
8
+ Project-URL: Repository, https://github.com/tudoujunha/macfw
9
+ Project-URL: Issues, https://github.com/tudoujunha/macfw/issues
10
+ Keywords: macos,pf,firewall,ufw,cli
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: System Administrators
14
+ Classifier: Operating System :: MacOS
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Topic :: Security
21
+ Classifier: Topic :: System :: Systems Administration
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Dynamic: license-file
26
+ Dynamic: requires-python
27
+
28
+ English | [简体中文](./README.zh-CN.md)
29
+
30
+ # macfw
31
+
32
+ `macfw` is a small `pf`-based firewall manager for macOS with a `ufw`-like CLI.
33
+
34
+ It is designed for one common use case:
35
+
36
+ - keep loopback, LAN, and trusted private ranges reachable
37
+ - keep outbound traffic open
38
+ - deny public inbound traffic by default
39
+ - allow or deny explicit inbound exceptions with a short CLI
40
+
41
+ In practice, you can think of it as:
42
+
43
+ - a macOS firewall CLI
44
+ - a `ufw`-like firewall tool for macOS
45
+ - a simple way to manage public inbound exposure on a Mac that behaves more like a server than a personal laptop
46
+
47
+ ## Why this exists
48
+
49
+ `macfw` exists to solve a gap that becomes obvious in IPv6-heavy home lab and self-hosting environments.
50
+
51
+ Many people now run a Mac, especially a Mac mini, as a small always-on server for tools, automation, coding agents, model runtimes, remote access, or NAS-like tasks. A particularly important example is people running OpenClaw on a Mac mini as a long-lived agent host. In that role, the machine is no longer just a daily personal computer. It starts behaving more like a Linux VPS, a home server, or a small self-hosted node that needs controlled inbound access.
52
+
53
+ On IPv4 networks, NAT often provides an extra layer between the machine and the public internet. On IPv6 networks, that assumption is much weaker. A Mac can end up directly reachable from the public internet, which means every listening service deserves deliberate review.
54
+
55
+ macOS does include firewall features, but the built-in experience is mostly app-oriented and GUI-oriented. It is not a close equivalent to the Linux `ufw` workflow many server users expect when they want to answer simple questions such as:
56
+
57
+ - which inbound ports are currently meant to be reachable from the public internet
58
+ - how do I allow only one port
59
+ - how do I allow only IPv4 or only IPv6
60
+ - how do I remove or deny a rule from the command line
61
+
62
+ `macfw` is built for that gap. It gives a Mac server or Mac mini a small command-line firewall workflow that feels much closer to `ufw`, while still using macOS `pf` underneath.
63
+
64
+ ## Who this is for
65
+
66
+ `macfw` is especially meant for people who:
67
+
68
+ - run OpenClaw or similar always-on agent workloads on a Mac mini
69
+ - run a Mac mini or another macOS machine as an always-on server
70
+ - use IPv6 and want tighter control over public inbound exposure
71
+ - prefer terminal-based rule management over GUI-only firewall tools
72
+ - want a simpler mental model similar to `ufw` rather than raw `pf.conf` editing
73
+
74
+ ## Status
75
+
76
+ `macfw` is currently an early `0.1.x` release. The rule model is usable, but the project should still be treated as a careful admin tool rather than a polished end-user app.
77
+
78
+ ## Requirements
79
+
80
+ - macOS
81
+ - Python 3.9+
82
+ - `pfctl`
83
+ - `sudo` access for commands that touch `/etc` or load `pf`
84
+
85
+ This project is for macOS only. It is not intended for Linux, BSD routers, or Windows.
86
+
87
+ ## Install
88
+
89
+ ### Option 1: install from a local clone
90
+
91
+ ```bash
92
+ git clone https://github.com/tudoujunha/macfw.git
93
+ cd macfw
94
+ python3 -m pip install .
95
+ ```
96
+
97
+ ### Option 2: install directly from GitHub
98
+
99
+ ```bash
100
+ python3 -m pip install git+https://github.com/tudoujunha/macfw.git
101
+ ```
102
+
103
+ ### Option 3: isolated CLI install with `pipx`
104
+
105
+ ```bash
106
+ pipx install git+https://github.com/tudoujunha/macfw.git
107
+ ```
108
+
109
+ After installation:
110
+
111
+ ```bash
112
+ macfw --version
113
+ ```
114
+
115
+ Once the package is published to PyPI, the intended installation command will be:
116
+
117
+ ```bash
118
+ pipx install macfw
119
+ ```
120
+
121
+ ## Before you start
122
+
123
+ You need to know which network interface receives the inbound traffic you want to protect.
124
+
125
+ Common examples:
126
+
127
+ - Wi-Fi: often `en0` or `en1`
128
+ - Ethernet or USB adapters: often another `enX`
129
+
130
+ Useful commands:
131
+
132
+ ```bash
133
+ ifconfig
134
+ networksetup -listallhardwareports
135
+ route -n get default
136
+ ```
137
+
138
+ If you are not sure, check which interface currently has your LAN or public IP address, then use that interface for `macfw install --interface ...`.
139
+
140
+ ## Quick start
141
+
142
+ Install the managed anchor and choose the network interface to protect:
143
+
144
+ ```bash
145
+ sudo macfw install --interface en1
146
+ ```
147
+
148
+ Check the current state before enabling anything:
149
+
150
+ ```bash
151
+ macfw status
152
+ sudo macfw status
153
+ ```
154
+
155
+ If you need SSH from the public internet, allow it before enabling the firewall:
156
+
157
+ ```bash
158
+ sudo macfw allow 22/tcp
159
+ ```
160
+
161
+ Enable the firewall:
162
+
163
+ ```bash
164
+ sudo macfw enable
165
+ ```
166
+
167
+ Show current state again:
168
+
169
+ ```bash
170
+ macfw status
171
+ sudo macfw status
172
+ ```
173
+
174
+ Disable or uninstall later:
175
+
176
+ ```bash
177
+ sudo macfw disable
178
+ sudo macfw uninstall
179
+ ```
180
+
181
+ ## First-time setup checklist
182
+
183
+ Recommended order:
184
+
185
+ 1. Install the anchor with the correct interface
186
+ 2. Review the default policy with `macfw status`
187
+ 3. Add any public inbound exceptions you need, such as `22/tcp`
188
+ 4. Enable the firewall
189
+ 5. Open a new test connection from the network you care about
190
+ 6. Only then close the old session
191
+
192
+ This matters because enabling `pf` can interrupt an already-established SSH connection.
193
+
194
+ ## Default policy
195
+
196
+ - allow loopback traffic
197
+ - allow inbound traffic from the active interface network
198
+ - allow inbound traffic from private RFC1918 IPv4 ranges
199
+ - allow inbound traffic from `100.64.0.0/10`
200
+ - allow inbound traffic from `fe80::/10` and `fd00::/8`
201
+ - allow outbound traffic
202
+ - deny public inbound traffic unless a rule explicitly allows it
203
+
204
+ ## Rule model
205
+
206
+ Each rule answers four questions:
207
+
208
+ - `from <source>`: who may connect
209
+ - `port <port|all>`: which local port is reachable
210
+ - `proto <proto>`: which protocol applies
211
+ - `family <both|ipv4|ipv6>`: which IP family applies
212
+
213
+ Supported protocols today:
214
+
215
+ - `tcp`
216
+ - `udp`
217
+ - `icmp`
218
+ - `icmp6`
219
+ - `any`
220
+
221
+ ## Common commands
222
+
223
+ ```bash
224
+ macfw allow 22/tcp
225
+ macfw allow 53/udp
226
+ macfw allow 22/tcp ipv6
227
+ macfw allow 22/tcp from any ipv4
228
+ macfw allow 22/tcp from 1.2.3.4
229
+ macfw allow 22/tcp from 2001:db8::1
230
+ macfw allow proto icmp ipv4
231
+ macfw allow from 192.168.0.0/16
232
+
233
+ macfw deny 22/tcp ipv6
234
+ macfw deny 22/tcp from 2001:db8::1
235
+
236
+ macfw delete 22/tcp
237
+ macfw delete 22/tcp ipv6
238
+ macfw delete deny 22/tcp ipv6
239
+ macfw delete from 192.168.0.0/16
240
+ ```
241
+
242
+ ## Common scenarios
243
+
244
+ Allow public SSH on IPv6 only:
245
+
246
+ ```bash
247
+ sudo macfw allow 22/tcp ipv6
248
+ ```
249
+
250
+ Allow public DNS on UDP:
251
+
252
+ ```bash
253
+ sudo macfw allow 53/udp
254
+ ```
255
+
256
+ Allow SSH only from one specific address:
257
+
258
+ ```bash
259
+ sudo macfw allow 22/tcp from 203.0.113.10
260
+ sudo macfw allow 22/tcp from 2001:db8::10
261
+ ```
262
+
263
+ Explicitly block a public IPv6 SSH rule:
264
+
265
+ ```bash
266
+ sudo macfw deny 22/tcp ipv6
267
+ ```
268
+
269
+ Remove a single matching rule without caring whether it is `allow` or `deny`:
270
+
271
+ ```bash
272
+ sudo macfw delete 22/tcp
273
+ ```
274
+
275
+ ## Delete matching behavior
276
+
277
+ `delete` uses two matching modes:
278
+
279
+ - if you specify `allow` or `deny`, deletion is constrained to that action
280
+ - if you do not specify an action, `macfw` looks for all matching rules
281
+
282
+ That means:
283
+
284
+ - if exactly one rule matches, `delete` removes it even if it is a `deny`
285
+ - if multiple rules match, `delete` stops and asks you to disambiguate with `allow`, `deny`, `ipv4`, `ipv6`, or a more specific source
286
+
287
+ Family matching works like this:
288
+
289
+ - omit `ipv4` or `ipv6`: broader family match
290
+ - specify `ipv4` or `ipv6`: exact family match
291
+
292
+ Examples:
293
+
294
+ ```bash
295
+ # removes 22/tcp, 22/tcp ipv4, or 22/tcp ipv6 if there is only one match
296
+ sudo macfw delete 22/tcp
297
+
298
+ # removes only an IPv6 rule
299
+ sudo macfw delete 22/tcp ipv6
300
+
301
+ # removes only a deny rule
302
+ sudo macfw delete deny 22/tcp ipv6
303
+ ```
304
+
305
+ ## Status output
306
+
307
+ `macfw status` shows:
308
+
309
+ - whether `macfw` is enabled
310
+ - whether live `pf` is enabled
311
+ - which interface is managed
312
+ - your user-defined rules first
313
+ - built-in trusted defaults
314
+ - the final default deny
315
+
316
+ If `pf` shows as `unknown`, run:
317
+
318
+ ```bash
319
+ sudo macfw status
320
+ ```
321
+
322
+ ## What `install`, `enable`, `reload`, and `disable` do
323
+
324
+ - `install`: creates the `macfw` anchor, injects the anchor hook into `/etc/pf.conf`, and writes the local config files
325
+ - `enable`: writes the active anchor rules, validates the `pf` config, and enables `pf` if needed
326
+ - `reload`: rewrites and reloads the anchor using the current config
327
+ - `disable`: keeps the config on disk but disables the active `macfw` policy
328
+ - `uninstall`: removes the anchor, restores the original `/etc/pf.conf` backup when available, and removes the local config files
329
+
330
+ ## Safety notes
331
+
332
+ Be careful when enabling or reloading rules over SSH.
333
+
334
+ - enabling `pf` can drop an already-established SSH session
335
+ - a newly opened LAN SSH session should still match the LAN allow rules
336
+ - a public SSH session will be dropped unless you explicitly allow it first
337
+
338
+ If you rely on public SSH access, add the rule before enabling:
339
+
340
+ ```bash
341
+ sudo macfw allow 22/tcp
342
+ sudo macfw enable
343
+ ```
344
+
345
+ If you rely on LAN SSH only, the default trusted LAN rules should permit a newly opened LAN session after the firewall is enabled. An already-established session can still drop when `pf` first becomes active.
346
+
347
+ ## How it works
348
+
349
+ `macfw` manages:
350
+
351
+ - a dedicated anchor at `/etc/pf.anchors/macfw`
352
+ - a hook in `/etc/pf.conf`
353
+ - a user config at `~/.config/macfw/config.json`
354
+ - a small state file at `~/.config/macfw/state.json`
355
+
356
+ `install` backs up the current `/etc/pf.conf` before modifying it. `uninstall` restores the backup when available.
357
+
358
+ ## Limitations
359
+
360
+ - there is no Homebrew formula yet
361
+ - there is no PyPI release yet
362
+ - interface detection is not automatic yet
363
+ - this tool is focused on inbound filtering on macOS `pf`
364
+ - this tool assumes you are comfortable using `sudo` and reading firewall state before enabling changes
365
+
366
+ ## Development
367
+
368
+ Run the test suite:
369
+
370
+ ```bash
371
+ python3 -m unittest discover -s tests -v
372
+ ```
373
+
374
+ Run directly from the repository checkout:
375
+
376
+ ```bash
377
+ PYTHONPATH=. python3 -m macfw --help
378
+ ```
379
+
380
+ For maintainer release steps, see:
381
+
382
+ - [`docs/publishing.md`](./docs/publishing.md)
383
+
384
+ ## License
385
+
386
+ MIT