mirror of
https://dev.azure.com/tstanciu94/PhantomMind/_git/Bitip
synced 2025-10-13 01:52:19 +03:00
599 lines
18 KiB
Markdown
599 lines
18 KiB
Markdown
# 🌍 Bitip - GeoIP Lookup Service
|
||
|
||
Bitip is a professional GeoIP lookup service that provides IP geolocation data through a REST API and user-friendly web interface. Built with Express.js, TypeScript, React, and MaxMind GeoLite2 databases.
|
||
|
||
## ✨ Features
|
||
|
||
- **🔍 IP Geolocation Lookup**: Get detailed location information for any public IP address
|
||
- **🌐 Web Interface**: Clean, professional web UI with interactive maps
|
||
- **📡 REST API**: Comprehensive API for single and batch IP lookups
|
||
- **📦 .NET Client Library**: Official Bitip.Client NuGet package with strongly-typed models and async support
|
||
- **<2A>🗺️ Interactive Maps**: Static preview and interactive map popups using OpenStreetMap/Leaflet
|
||
- **🔐 API Key Authentication**: Secure access with configurable rate limiting
|
||
- **⚡ Performance**: In-memory caching and efficient database access
|
||
- **📊 Structured Logging**: Optional integration with Seq for advanced logging
|
||
- **🐳 Docker Ready**: Production deployment with Docker and geoipupdate integration
|
||
- **🔧 Configurable**: Runtime configuration via environment variables
|
||
|
||
## 📚 Client Libraries
|
||
|
||
### .NET / C#
|
||
|
||
Official NuGet package with full async/await support and dependency injection integration:
|
||
|
||
```bash
|
||
dotnet add package Bitip.Client
|
||
```
|
||
|
||
```csharp
|
||
// Register in your DI container
|
||
services.UseBitipClient("https://your-bitip-instance.com/api", "your-api-key");
|
||
|
||
// Inject and use
|
||
public class MyService
|
||
{
|
||
private readonly IBitipClient _bitipClient;
|
||
|
||
public MyService(IBitipClient bitipClient)
|
||
{
|
||
_bitipClient = bitipClient;
|
||
}
|
||
|
||
public async Task<IpLocation> LookupAsync(string ip)
|
||
{
|
||
return await _bitipClient.GetIpLocation(ip);
|
||
}
|
||
}
|
||
```
|
||
|
||
See [src/clients/dotnet/Bitip.Client/README.md](src/clients/dotnet/Bitip.Client/README.md) for complete documentation.
|
||
|
||
### Node.js / JavaScript
|
||
|
||
Coming soon! In development at [src/clients/node](src/clients/node).
|
||
|
||
### Other Languages
|
||
|
||
Use the REST API directly - see API documentation below.
|
||
|
||
## 🚀 Quick Start
|
||
|
||
### Local Development (No Docker Required)
|
||
|
||
#### Prerequisites
|
||
|
||
- Node.js >= 18.0.0
|
||
- npm >= 9.0.0
|
||
- MaxMind GeoLite2 databases (download from https://www.maxmind.com/en/geolite2/signup or use geoipupdate)
|
||
|
||
#### 1. Clone and Setup
|
||
|
||
```bash
|
||
git clone <repository-url>
|
||
cd Bitip
|
||
```
|
||
|
||
#### 2. Install Dependencies
|
||
|
||
```bash
|
||
npm run install:all
|
||
```
|
||
|
||
#### 3. Configure Environment
|
||
|
||
Create a `.env` file in the root directory:
|
||
|
||
```env
|
||
# API Keys (change these for production!)
|
||
FRONTEND_API_KEY=frontend-dev-key
|
||
EXTERNAL_API_KEYS=external-dev-key-1,external-dev-key-2
|
||
|
||
# Server Configuration
|
||
PORT=5172
|
||
BASE_PATH=/
|
||
NODE_ENV=development
|
||
ENABLE_HTTPS_SECURITY=false
|
||
LOG_LEVEL=debug # debug | info | warning | error
|
||
|
||
# Database Path - Point to your MaxMind databases location
|
||
# Both GeoLite2-City.mmdb and GeoLite2-ASN.mmdb are required
|
||
MAXMIND_DB_PATH=D:\tools\maxmind-dbs # Windows
|
||
# MAXMIND_DB_PATH=/usr/share/maxmind # Linux/Mac
|
||
|
||
# Rate Limiting Configuration
|
||
FRONTEND_RATE_WINDOW_MS=60000
|
||
FRONTEND_RATE_MAX=30
|
||
EXTERNAL_RATE_WINDOW_MS=60000
|
||
EXTERNAL_RATE_MAX=1000
|
||
|
||
# Batch Configuration
|
||
BATCH_LIMIT=100
|
||
DEBOUNCE_MS=2000
|
||
|
||
# Seq Logging (Optional)
|
||
# SEQ_URL=http://localhost:5341
|
||
# SEQ_API_KEY=your-seq-api-key
|
||
```
|
||
|
||
#### 4. Start Development Servers
|
||
|
||
```bash
|
||
npm run dev
|
||
```
|
||
|
||
This will start:
|
||
|
||
- Backend API server on http://localhost:5172
|
||
- Frontend dev server on http://localhost:5173 (or next available port)
|
||
- Frontend proxies API requests to backend
|
||
|
||
#### 5. Access the Application
|
||
|
||
- **Web Interface**: http://localhost:5173 (or the port shown in console)
|
||
- **API Endpoint**: http://localhost:5172/api
|
||
- **Health Check**: http://localhost:5172/api/health
|
||
|
||
### Production Deployment (Docker)
|
||
|
||
#### Prerequisites
|
||
|
||
- Docker and Docker Compose
|
||
- MaxMind GeoLite2 account (free): https://www.maxmind.com/en/geolite2/signup
|
||
|
||
#### 1. Configure Environment
|
||
|
||
Edit `.env` file with your MaxMind credentials and logging level:
|
||
|
||
```env
|
||
GEOIPUPDATE_ACCOUNT_ID=your_account_id_here
|
||
GEOIPUPDATE_LICENSE_KEY=your_license_key_here
|
||
FRONTEND_API_KEY=your-secure-frontend-api-key-here
|
||
EXTERNAL_API_KEYS=your-secure-external-api-key-1,your-secure-external-api-key-2
|
||
LOG_LEVEL=warning # Recommended for production (debug | info | warning | error)
|
||
```
|
||
|
||
#### 2. Start Services
|
||
|
||
```bash
|
||
docker-compose up -d
|
||
```
|
||
|
||
**Or with Docker run:**
|
||
|
||
```bash
|
||
# Build image
|
||
docker build -t bitip-geoip:latest .
|
||
|
||
# Run with custom log level
|
||
docker run -d \
|
||
-p 5172:5172 \
|
||
-e LOG_LEVEL=warning \
|
||
-e FRONTEND_API_KEY=your-api-key \
|
||
-v /path/to/maxmind-dbs:/usr/share/maxmind \
|
||
bitip-geoip:latest
|
||
```
|
||
|
||
**Available log levels:**
|
||
|
||
- `debug` - All logs (verbose, for development/troubleshooting)
|
||
- `info` - Info + warnings + errors (default)
|
||
- `warning` - Warnings + errors only (recommended for production)
|
||
- `error` - Errors only (minimal logging)
|
||
|
||
#### 3. Access the Service
|
||
|
||
- **Web Interface**: http://localhost:5172
|
||
- **API Endpoint**: http://localhost:5172/api
|
||
- **Health Check**: http://localhost:5172/api/health
|
||
|
||
## 📖 API Documentation
|
||
|
||
### Authentication
|
||
|
||
All API requests require an API key sent via header or query parameter:
|
||
|
||
```bash
|
||
# Via Header (recommended)
|
||
curl -H "X-API-Key: your-api-key" http://localhost:5172/api/lookup?ip=8.8.8.8
|
||
|
||
# Via Query Parameter
|
||
curl "http://localhost:5172/api/lookup?ip=8.8.8.8&apikey=your-api-key"
|
||
```
|
||
|
||
### Endpoints
|
||
|
||
#### Get Current IP
|
||
|
||
```http
|
||
GET /api/ip
|
||
```
|
||
|
||
Returns the client's current IP address.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ip": "203.0.113.42"
|
||
}
|
||
```
|
||
|
||
#### Simple IP Lookup
|
||
|
||
```http
|
||
GET /api/lookup?ip=8.8.8.8
|
||
```
|
||
|
||
Returns basic location information:
|
||
|
||
```json
|
||
{
|
||
"ip": "8.8.8.8",
|
||
"country": "United States",
|
||
"country_code": "US",
|
||
"is_in_european_union": false,
|
||
"region": "California",
|
||
"region_code": "CA",
|
||
"city": "Mountain View",
|
||
"latitude": 37.4056,
|
||
"longitude": -122.0775,
|
||
"timezone": "America/Los_Angeles",
|
||
"postal_code": "94043",
|
||
"continent_code": "NA",
|
||
"continent_name": "North America",
|
||
"organization": "Google LLC",
|
||
"asn": 15169
|
||
}
|
||
```
|
||
|
||
#### Detailed IP Lookup
|
||
|
||
```http
|
||
GET /api/lookup/detailed?ip=8.8.8.8
|
||
```
|
||
|
||
Returns comprehensive MaxMind database information including all available fields.
|
||
|
||
#### Batch IP Lookup
|
||
|
||
```http
|
||
POST /api/lookup/batch
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"ips": ["8.8.8.8", "1.1.1.1", "208.67.222.222"]
|
||
}
|
||
```
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"results": [
|
||
{
|
||
"ip": "8.8.8.8",
|
||
"country": "United States",
|
||
...
|
||
},
|
||
{
|
||
"ip": "1.1.1.1",
|
||
"country": "Australia",
|
||
...
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
#### Health Check
|
||
|
||
```http
|
||
GET /api/health
|
||
```
|
||
|
||
Returns service health status including database connectivity.
|
||
|
||
### Error Handling
|
||
|
||
The API returns appropriate HTTP status codes:
|
||
|
||
- `400` - Bad Request (invalid IP, private IP, validation errors)
|
||
- `401` - Unauthorized (missing or invalid API key)
|
||
- `404` - Not Found (IP not in database)
|
||
- `429` - Too Many Requests (rate limit exceeded)
|
||
- `500` - Internal Server Error
|
||
- `503` - Service Unavailable (database maintenance)
|
||
|
||
## 🛠️ Development
|
||
|
||
### Project Structure
|
||
|
||
```
|
||
Bitip/
|
||
├── src/
|
||
│ ├── backend/ # Express.js API server
|
||
│ │ ├── routes/ # API route handlers
|
||
│ │ ├── services/ # Business logic (GeoIP, config, logger)
|
||
│ │ ├── middleware/ # Express middleware (auth, rate limiting)
|
||
│ │ ├── types/ # TypeScript type definitions
|
||
│ │ ├── index.ts # Main server entry point
|
||
│ │ ├── nodemon.json # Nodemon configuration
|
||
│ │ ├── tsconfig.json # TypeScript configuration
|
||
│ │ └── package.json # Backend dependencies
|
||
│ └── frontend/ # React web application
|
||
│ ├── src/
|
||
│ │ ├── components/ # React components (MapComponent)
|
||
│ │ ├── services/ # API client services
|
||
│ │ ├── types/ # TypeScript types
|
||
│ │ ├── App.tsx # Main App component
|
||
│ │ ├── App.css # Application styles
|
||
│ │ └── main.tsx # React entry point
|
||
│ ├── index.html # HTML template
|
||
│ ├── vite.config.ts # Vite configuration
|
||
│ ├── tsconfig.json # TypeScript configuration
|
||
│ └── package.json # Frontend dependencies
|
||
├── content/ # Content files (Overview.json, ReleaseNotes.json)
|
||
├── docs/ # Documentation (PRD, tech stack)
|
||
├── .env # Environment variables (not in git)
|
||
├── .env.example # Example environment file
|
||
├── Dockerfile # Production Docker image
|
||
├── package.json # Root package configuration
|
||
└── README.md
|
||
```
|
||
|
||
### Available Scripts
|
||
|
||
```bash
|
||
# Development
|
||
npm run dev # Start both frontend and backend in dev mode
|
||
npm run dev:backend # Start backend development server only
|
||
npm run dev:frontend # Start frontend development server only
|
||
|
||
# Building
|
||
npm run build # Build both frontend and backend for production
|
||
npm run build:backend # Build backend only
|
||
npm run build:frontend # Build frontend only
|
||
|
||
# Production
|
||
npm start # Start production backend server (after build)
|
||
|
||
# Code Quality
|
||
npm run lint # Lint both frontend and backend
|
||
npm run lint:fix # Fix linting issues
|
||
npm run format # Format code with Prettier
|
||
|
||
# Utilities
|
||
npm run clean # Clean build artifacts
|
||
npm run install:all # Install all dependencies (root + backend + frontend)
|
||
```
|
||
|
||
### Technology Stack
|
||
|
||
**Backend:**
|
||
|
||
- Express.js 5.x with TypeScript
|
||
- @maxmind/geoip2-node 6.x - GeoIP database reader
|
||
- node-cache - In-memory caching
|
||
- express-rate-limit 8.x - Rate limiting
|
||
- helmet - Security headers
|
||
- joi - Request validation
|
||
- seq-logging - Optional structured logging
|
||
- **tsup** - Modern bundler for fast builds (88ms vs ~1000ms with tsc) ⚡
|
||
|
||
**Frontend:**
|
||
|
||
- React 19.x with TypeScript
|
||
- Vite 7.x - Build tool and dev server
|
||
- Leaflet & react-leaflet - Interactive maps
|
||
- Axios - HTTP client
|
||
- OpenStreetMap - Map tiles
|
||
|
||
**Development Tools:**
|
||
|
||
- TypeScript 5.x
|
||
- ESLint & Prettier
|
||
- nodemon - Auto-restart on changes
|
||
- tsx - TypeScript execution
|
||
|
||
**Build System:**
|
||
|
||
- **tsup** (backend) - esbuild-based bundler with ESM support, no `.js` extensions needed
|
||
- **Vite** (frontend) - Lightning-fast HMR and optimized production builds
|
||
|
||
> 📖 See [tsup Migration Guide](docs/tsup-migration.md) for details on the modern build system.
|
||
|
||
## ⚙️ Configuration
|
||
|
||
### Environment Variables
|
||
|
||
| Variable | Default | Description |
|
||
| -------------------------- | ---------------------- | ----------------------------------------------------- |
|
||
| `PORT` | `5172` | Server port |
|
||
| `BASE_PATH` | `/` | Application base path |
|
||
| `NODE_ENV` | `development` | Environment mode (development/production) |
|
||
| `ENABLE_HTTPS_SECURITY` | `false` | Enable HTTPS security headers (CSP, HSTS, COOP, CORP) |
|
||
| `MAXMIND_DB_PATH` | `/usr/share/maxmind` | MaxMind database directory |
|
||
| `FRONTEND_API_KEY` | `frontend-default-key` | Frontend API key |
|
||
| `EXTERNAL_API_KEYS` | `external-default-key` | External API keys (comma-separated) |
|
||
| `FRONTEND_ALLOWED_ORIGINS` | `http://localhost:*` | Allowed CORS origins for frontend (comma-separated) |
|
||
| `FRONTEND_RATE_WINDOW_MS` | `60000` | Frontend rate limit window (milliseconds) |
|
||
| `FRONTEND_RATE_MAX` | `30` | Frontend rate limit max requests |
|
||
| `EXTERNAL_RATE_WINDOW_MS` | `60000` | External rate limit window (milliseconds) |
|
||
| `EXTERNAL_RATE_MAX` | `1000` | External rate limit max requests |
|
||
| `BATCH_LIMIT` | `100` | Maximum IPs per batch request |
|
||
| `DEBOUNCE_MS` | `2000` | Frontend input debounce delay (milliseconds) |
|
||
| `SEQ_URL` | - | Seq logging server URL (optional) |
|
||
| `SEQ_API_KEY` | - | Seq API key (optional) |
|
||
|
||
### MaxMind Database Setup
|
||
|
||
The service requires both MaxMind GeoLite2-City and GeoLite2-ASN databases. You have two options:
|
||
|
||
**Option 1: Manual Download**
|
||
|
||
1. Sign up at https://www.maxmind.com/en/geolite2/signup
|
||
2. Download both databases (`.mmdb` files):
|
||
- GeoLite2-City.mmdb
|
||
- GeoLite2-ASN.mmdb
|
||
3. Place them in the same directory (e.g., `D:\tools\maxmind-dbs` on Windows)
|
||
4. Set `MAXMIND_DB_PATH` environment variable to that directory
|
||
|
||
**Option 2: Using geoipupdate (Production)**
|
||
|
||
- Use the provided `docker-compose.yml` which includes geoipupdate service
|
||
- geoipupdate automatically downloads and updates both databases
|
||
- Both services share a Docker volume for database access
|
||
|
||
### Rate Limiting
|
||
|
||
Bitip implements different rate limiting for frontend and external API consumers:
|
||
|
||
- **Frontend**: More restrictive limits for web UI usage (default: 100 req/min)
|
||
- **External**: Higher limits for programmatic API access (default: 1000 req/min)
|
||
|
||
Rate limits are fully configurable via environment variables and include standard HTTP headers in responses.
|
||
|
||
### HTTPS Security Headers
|
||
|
||
The `ENABLE_HTTPS_SECURITY` variable controls security headers provided by Helmet:
|
||
|
||
- **`false` (default)**: Disables CSP, HSTS, COOP, and CORP headers - required for HTTP deployments
|
||
- **`true`**: Enables all security headers - use when deploying behind HTTPS reverse proxy (nginx, Traefik, etc.)
|
||
|
||
**Important**: If running on plain HTTP without a reverse proxy, keep this set to `false`. Browser security policies will block resources if HTTPS security headers are enabled on HTTP connections.
|
||
|
||
## 🐳 Docker Deployment
|
||
|
||
### Production Setup
|
||
|
||
The service is designed to run alongside MaxMind's geoipupdate service:
|
||
|
||
```bash
|
||
# Start both services
|
||
docker-compose up -d
|
||
|
||
# View logs
|
||
docker-compose logs -f bitip
|
||
|
||
# Stop services
|
||
docker-compose down
|
||
```
|
||
|
||
The `docker-compose.yml` includes:
|
||
|
||
- **geoipupdate**: Downloads and updates MaxMind databases
|
||
- **bitip**: Main application server (API + Web UI)
|
||
- **Shared volume**: For database access between services
|
||
|
||
### Health Monitoring
|
||
|
||
The service includes comprehensive health checks:
|
||
|
||
- Docker health check endpoint: `/api/health`
|
||
- Database connectivity verification
|
||
- Service status monitoring
|
||
|
||
## 🔧 Troubleshooting
|
||
|
||
### Common Issues
|
||
|
||
**1. Database Not Found**
|
||
|
||
- Ensure both databases are downloaded to the path specified in `MAXMIND_DB_PATH`
|
||
- Check that both `GeoLite2-City.mmdb` and `GeoLite2-ASN.mmdb` files exist in that directory
|
||
- Verify file permissions (read access required)
|
||
|
||
**2. TypeScript Errors**
|
||
|
||
- Run `npm run install:all` to ensure all dependencies are installed
|
||
- Check that Node.js version is >= 18.0.0
|
||
- Try deleting `node_modules` and reinstalling
|
||
|
||
**3. API Authentication Errors**
|
||
|
||
- Verify API key in `.env` file matches the one you're using
|
||
- Check `X-API-Key` header or `apikey` query parameter format
|
||
- Ensure API key doesn't contain extra spaces
|
||
|
||
**4. Rate Limiting**
|
||
|
||
- Check rate limit headers in API responses (`X-RateLimit-*`)
|
||
- Adjust rate limiting configuration if needed
|
||
- Use external API keys for higher limits
|
||
|
||
**5. Map Display Issues**
|
||
|
||
- Verify internet connectivity for OpenStreetMap tiles
|
||
- Check browser console for JavaScript errors
|
||
- Ensure Leaflet CSS is loading correctly
|
||
|
||
**6. Port Already in Use**
|
||
|
||
- Frontend dev server will auto-increment port (5173, 5174, etc.)
|
||
- Backend port can be changed via `PORT` environment variable
|
||
- Check for other services using the same ports
|
||
|
||
### Logs and Debugging
|
||
|
||
- Application logs are printed to console
|
||
- Use `npm run dev` for detailed development logs
|
||
- Configure Seq integration for structured logging
|
||
- Docker logs: `docker-compose logs -f bitip`
|
||
|
||
## 📦 Package Versions
|
||
|
||
**Current versions (as of project creation):**
|
||
|
||
- Major packages are on stable versions but not latest
|
||
- Consider updating for newer features and security fixes
|
||
- Check `npm outdated` for available updates
|
||
- Test thoroughly after major version updates
|
||
|
||
**Key outdated packages:**
|
||
|
||
- Express 4.x (5.x available but still beta)
|
||
- React 18.x (19.x available)
|
||
- Vite 4.x (7.x available - major update)
|
||
- Many dev dependencies have newer versions
|
||
|
||
## 📄 License
|
||
|
||
**Copyright © 2025 Tudor Stanciu. All rights reserved.**
|
||
|
||
This software is **proprietary** and confidential. Unauthorized use, copying, modification, distribution, or reverse engineering of this software, in whole or in part, is strictly prohibited without explicit written permission from the copyright holder.
|
||
|
||
### License Summary
|
||
|
||
- ✅ **Evaluation Period**: 30-day trial for evaluation purposes
|
||
- ✅ **Approved Use**: Requires explicit written approval from Tudor Stanciu
|
||
- ❌ **No Redistribution**: Cannot be distributed, sublicensed, or transferred to third parties
|
||
- ❌ **No Modification**: Cannot be modified or create derivative works without permission
|
||
- ❌ **No Commercial Use**: Cannot be used for commercial services without separate license
|
||
|
||
### Obtaining a License
|
||
|
||
For licensing inquiries, commercial use, or approval requests:
|
||
|
||
**Contact**: Tudor Stanciu
|
||
**Email**: tudor.stanciu94@gmail.com
|
||
|
||
Please include:
|
||
|
||
- Intended use case
|
||
- Organization name and size
|
||
- Expected deployment scale
|
||
- Duration of use
|
||
|
||
See [LICENSE](LICENSE) file for complete terms and conditions.
|
||
|
||
## 🙏 Acknowledgments
|
||
|
||
- **MaxMind** for providing GeoLite2 databases
|
||
- **OpenStreetMap** for map tiles
|
||
- **Leaflet** for interactive mapping
|
||
- All open-source contributors
|
||
|
||
---
|
||
|
||
**Bitip** - Professional GeoIP Lookup Service 🌍
|
||
Built with ❤️ using Express.js, React, and MaxMind GeoLite2
|