|
27 | 27 | from tools.utils_gui import set_settings, get_settings |
28 | 28 | from tools.utils import goto, is_connected, get_default_iface |
29 | 29 | from tools.pfctl import (ensure_pf_enabled, install_anchor, block_all_for, unblock_all_for, |
30 | | - block_port, unblock_port, is_port_blocked, list_blocked_ports, clear_all_port_blocks) |
| 30 | + block_port, unblock_port, is_port_blocked, list_blocked_ports, clear_all_port_blocks, |
| 31 | + block_ip, unblock_ip, list_blocked_ips) |
31 | 32 |
|
32 | 33 | from assets import * |
33 | 34 |
|
@@ -207,6 +208,27 @@ def setup_ui(self): |
207 | 208 |
|
208 | 209 | layout.addWidget(quick_group) |
209 | 210 |
|
| 211 | + # IP blocking section |
| 212 | + ip_group = QGroupBox('Block IP Address') |
| 213 | + ip_layout = QHBoxLayout(ip_group) |
| 214 | + |
| 215 | + self.ipInput = QLineEdit() |
| 216 | + self.ipInput.setPlaceholderText('e.g. 192.168.1.100') |
| 217 | + ip_layout.addWidget(QLabel('IP:')) |
| 218 | + ip_layout.addWidget(self.ipInput) |
| 219 | + |
| 220 | + self.ipDirCombo = QComboBox() |
| 221 | + self.ipDirCombo.addItems(['Both', 'In', 'Out']) |
| 222 | + ip_layout.addWidget(QLabel('Dir:')) |
| 223 | + ip_layout.addWidget(self.ipDirCombo) |
| 224 | + |
| 225 | + self.blockIpBtn = QPushButton('Block IP') |
| 226 | + self.blockIpBtn.clicked.connect(self.block_ip_clicked) |
| 227 | + self.blockIpBtn.setStyleSheet('background-color: #c0392b; color: white;') |
| 228 | + ip_layout.addWidget(self.blockIpBtn) |
| 229 | + |
| 230 | + layout.addWidget(ip_group) |
| 231 | + |
210 | 232 | # Common ports with checkboxes |
211 | 233 | common_group = QGroupBox('Common Ports (Click to Toggle)') |
212 | 234 | common_layout = QVBoxLayout(common_group) |
@@ -268,6 +290,15 @@ def quick_block(self): |
268 | 290 |
|
269 | 291 | self.refresh_list() |
270 | 292 |
|
| 293 | + def block_ip_clicked(self): |
| 294 | + ip = self.ipInput.text().strip() |
| 295 | + if not ip: |
| 296 | + return |
| 297 | + direction = self.ipDirCombo.currentText().lower() |
| 298 | + block_ip(self.iface, ip, direction) |
| 299 | + self.ipInput.clear() |
| 300 | + self.refresh_list() |
| 301 | + |
271 | 302 | def on_item_changed(self, item): |
272 | 303 | port = item.data(Qt.UserRole) |
273 | 304 | if item.checkState() == Qt.Checked: |
@@ -297,26 +328,46 @@ def refresh_list(self): |
297 | 328 | self.portList.blockSignals(False) |
298 | 329 |
|
299 | 330 | def refresh_blocked_list(self): |
300 | | - """Refresh just the blocked ports display.""" |
| 331 | + """Refresh just the blocked ports and IPs display.""" |
301 | 332 | self.blockedList.clear() |
302 | | - blocked = list_blocked_ports() |
| 333 | + |
| 334 | + # Add blocked ports |
| 335 | + blocked_ports = list_blocked_ports() |
303 | 336 | seen = set() |
304 | | - for port, proto, direction in blocked: |
| 337 | + for port, proto, direction in blocked_ports: |
305 | 338 | key = (port, proto) |
306 | 339 | if key not in seen: |
307 | 340 | seen.add(key) |
308 | | - item = QListWidgetItem(f'{port} ({proto.upper()}) - {direction}') |
309 | | - item.setData(Qt.UserRole, (port, proto)) |
| 341 | + item = QListWidgetItem(f'Port {port} ({proto.upper()}) - {direction}') |
| 342 | + item.setData(Qt.UserRole, ('port', port, proto)) |
| 343 | + self.blockedList.addItem(item) |
| 344 | + |
| 345 | + # Add blocked IPs |
| 346 | + blocked_ips = list_blocked_ips() |
| 347 | + seen_ips = set() |
| 348 | + for ip, direction in blocked_ips: |
| 349 | + if ip not in seen_ips: |
| 350 | + seen_ips.add(ip) |
| 351 | + item = QListWidgetItem(f'IP {ip} - {direction}') |
| 352 | + item.setData(Qt.UserRole, ('ip', ip)) |
310 | 353 | self.blockedList.addItem(item) |
311 | 354 |
|
312 | 355 | def unblock_selected(self): |
313 | 356 | for item in self.blockedList.selectedItems(): |
314 | | - port, proto = item.data(Qt.UserRole) |
315 | | - unblock_port(port, proto) |
| 357 | + data = item.data(Qt.UserRole) |
| 358 | + if data[0] == 'port': |
| 359 | + _, port, proto = data |
| 360 | + unblock_port(port, proto) |
| 361 | + elif data[0] == 'ip': |
| 362 | + _, ip = data |
| 363 | + unblock_ip(ip) |
316 | 364 | self.refresh_list() |
317 | 365 |
|
318 | 366 | def clear_all(self): |
319 | 367 | clear_all_port_blocks() |
| 368 | + # Also clear blocked IPs |
| 369 | + for ip, _ in list_blocked_ips(): |
| 370 | + unblock_ip(ip) |
320 | 371 | self.refresh_list() |
321 | 372 |
|
322 | 373 |
|
|
0 commit comments