# 🛡️ BarcoShield — PHP Web Application Firewall

A drop-in PHP security layer for your applications.  
Compatible with any LAMP stack — no Composer required.

---

## Quick Start

### 1. Copy files to your server

```
/your-project/
    shield.php          ← Core engine (required)
    admin/
        index.php       ← Admin dashboard (optional, protect this!)
    logs/               ← Auto-created, needs write permission
```

### 2. Configure `shield.php`

Open `shield.php` and update the `$SHIELD_CONFIG` block at the top:

```php
'db_dsn'   => 'mysql:host=localhost;dbname=YOUR_DB;charset=utf8mb4',
'db_user'  => 'YOUR_DB_USER',
'db_pass'  => 'YOUR_DB_PASS',
```

Set `'db_logging' => false` if you want file-only logging (no DB needed).

### 3. Add one line to each PHP app

```php
<?php
require_once '/path/to/shield.php';  // ← Add as very first line
// ... rest of your app
```

### 4. Create the database (if using DB logging)

The tables are auto-created on first run. Just make sure the DB user
has CREATE TABLE permissions on the target database, then visit any
protected page once.

Or run manually:
```sql
CREATE DATABASE shield_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL ON shield_db.* TO 'shield_user'@'localhost' IDENTIFIED BY 'yourpass';
```

---

## Admin Dashboard

### Protect with .htaccess

Create `/admin/.htaccess`:
```apache
AuthType Basic
AuthName "Shield Admin"
AuthUserFile /var/www/.htpasswd
Require valid-user
```

Or restrict by IP:
```apache
Order Deny,Allow
Deny from all
Allow from YOUR.IP.ADDRESS
```

### Set admin password

In `admin/index.php`, replace the `ADMIN_PASS` constant:

```php
// Run this once in a separate PHP file to generate the hash:
echo password_hash('your-secure-password', PASSWORD_BCRYPT);
```

Then paste the output into:
```php
define('ADMIN_PASS', '$2y$12$the_hash_from_above...');
```

---

## Brute Force — App Integration

BarcoShield tracks failed login attempts automatically on POST requests
to login paths. To count a failed attempt, call this after a failed
credential check in your login handler:

```php
if (!password_verify($inputPass, $storedHash)) {
    BarcoShield::loginFailed();  // ← triggers the brute force counter
    $error = 'Invalid credentials.';
}
```

---

## Configuration Reference

| Key | Default | Description |
|-----|---------|-------------|
| `sqli_xss_enabled` | `true` | Enable SQLi/XSS scanning |
| `sqli_xss_action` | `'block'` | `'block'` or `'log'` only |
| `flood_requests` | `120` | Max requests per window |
| `flood_window_seconds` | `60` | Rolling window duration |
| `flood_ban_seconds` | `300` | Temp ban on flood (5 min) |
| `bruteforce_attempts` | `5` | Failed logins before ban |
| `bruteforce_window` | `300` | 5-min rolling window |
| `bruteforce_ban` | `900` | 15-min ban after threshold |
| `login_paths` | `['/login', '/admin', ...]` | Paths to watch for brute force |
| `banned_ips` | `[]` | Permanent IP block list |
| `banned_cidrs` | `[]` | CIDR range blocks |
| `banned_countries` | `[]` | ISO-2 country codes to block |
| `geo_enabled` | `false` | Enable geo-lookup (ip-api.com) |
| `upload_enabled` | `true` | Scan file uploads |
| `allowed_mime_types` | *(list)* | Permitted MIME types |
| `blocked_extensions` | *(list)* | Blocked file extensions |
| `max_upload_size` | `10485760` | Max upload size (10MB) |
| `scan_upload_content` | `true` | Scan file bytes for PHP code |
| `block_redirect` | `''` | Redirect URL on block (empty = show block page) |
| `debug_mode` | `false` | Show threat type on block page |

---

## Manual Banning via Code

```php
// Ban an IP for 1 hour
BarcoShield::addBan('1.2.3.4', 'MANUAL', 3600);

// Unban
BarcoShield::unban('1.2.3.4');
```

---

## File Structure

```
shield.php          Main engine + config
admin/
  index.php         Admin dashboard (login + UI)
logs/
  shield_YYYY-MM-DD.log   Daily text logs (fallback)
  rate_*.json             Rate limit state (file fallback)
  geo_*.json              Geo lookup cache
```

---

## Security Notes

- Never set `debug_mode = true` in production
- Keep `shield.php` outside the web root if possible, and use `require_once` from above
- Restrict `admin/` with both `.htaccess` IP restriction AND the built-in password
- Rotate the admin password regularly
- Ensure `logs/` is not web-accessible (add `.htaccess` with `Deny from all`)

---

## Requirements

- PHP 8.0+
- MySQL 5.7+ / MariaDB 10.3+ (optional — file logging works without DB)
- `finfo` extension (standard on most LAMP stacks — for MIME detection)
- Write permission on `logs/` directory
