This repository contains the AWS Lambda function and API Gateway setup instructions for controlling a personal OpenVPN server on AWS. It's part of a larger project created during a sabbatical in Taipei to build a complete VPN solution with iOS app control. The Lambda code was generated with assistance from AI tools (ChatGPT and Claude).
This API provides a secure interface to control an EC2 instance running OpenVPN through:
- REST API endpoints using API Gateway
- Lambda function for EC2 control
- API key authentication
- Status monitoring capabilities
The API is designed to work with:
- VPN Infrastructure created via Terraform
- VPNControl iOS App for remote management
The API provides these endpoints:
POST /vpn
GET /vpn/status
start: Start the VPN instancestop: Stop the VPN instancestatus: Get current instance state
The Lambda function (handler.py) manages EC2 instance operations:
def lambda_handler(event, context):
action = ""
if "queryStringParameters" in event and event["queryStringParameters"] is not None:
action = event["queryStringParameters"].get("action", "").lower()
elif "action" in event and event["action"] is not None:
action = event.get("action", "").lower()
# Handle start/stop/status actions
try:
if action == "start":
ec2.start_instances(InstanceIds=[INSTANCE_ID])
message = f"Instance {INSTANCE_ID} is starting."
# ... additional action handling- Go to IAM Console → Create role
- Select AWS Service → Lambda
- Attach these policies:
- AWSLambdaBasicExecutionRole
- Custom EC2 control policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:StartInstances",
"ec2:StopInstances",
"ec2:DescribeInstances"
],
"Resource": "arn:aws:ec2:your-region:your-account-id:instance/*"
}
]
}-
Create new Lambda function:
- Author from scratch
- Runtime: Python 3.9+
- Attach IAM role from Step 1
-
Set environment variables:
EC2_ID: Your VPN instance ID
-
Upload
handler.pycode
- Create REST API
- Create resource "/vpn"
- Add methods:
- POST for control actions
- GET for status
- Integration setup:
- Type: Lambda Function
- Lambda Proxy integration: Yes
- Lambda Function: Select your function
-
Enable API key requirement:
- Method Request settings
- Set "API Key Required" to true
-
Create API key:
- API Gateway → API Keys
- Create new key
- Add to Usage Plan
-
CORS configuration (if needed):
- Enable CORS in API Gateway
- Allow necessary headers
- Deploy API:
- Create new stage (e.g., "prod")
- Note the Invoke URL
- Save API key for client use
curl -X POST "https://your-api-id.execute-api.your-region.amazonaws.com/prod/vpn" \
-H "x-api-key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"action": "start"}'curl -X GET "https://your-api-id.execute-api.your-region.amazonaws.com/prod/vpn/status" \
-H "x-api-key: your-api-key"curl -X POST "https://your-api-id.execute-api.your-region.amazonaws.com/prod/vpn" \
-H "x-api-key: your-api-key" \
-H "Content-Type: application/json" \
-d '{"action": "stop"}'Successful response:
{
"statusCode": 200,
"body": {
"message": "Instance i-1234567890abcdef0 is starting."
}
}Error response:
{
"statusCode": 400,
"body": {
"message": "Invalid action. Use 'start', 'stop', or 'status'."
}
}-
API Key Protection:
- Never commit API keys to source control
- Rotate keys periodically
- Use Usage Plans to limit request rates
-
IAM Permissions:
- Follow principle of least privilege
- Restrict EC2 actions to specific instance
- Enable CloudWatch logging
-
Network Security:
- Enable HTTPS only
- Configure CORS appropriately
- Consider VPC endpoints for added security
-
CloudWatch Logs:
- Lambda function logs
- API Gateway access logs
- Errors and debugging information
-
Metrics to Monitor:
- API Gateway 4xx/5xx errors
- Lambda execution duration
- Lambda throttling
- API key usage
- Fork the repository
- Create a feature branch
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
- AWS for the serverless platform
- ChatGPT and Claude for code generation assistance
For questions or suggestions, please open an issue in the repository.