Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*
!mmar
2 changes: 2 additions & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
golang 1.25.1
golangci-lint 2.5.0
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,19 +188,20 @@ MMAR supports authentication using API keys to control tunnel creation and limit

### Server Configuration

To enable authentication on the server, create an API keys file (YAML format) and specify it when starting the server:

```yaml
# api-keys.yaml
key1: 100
test-token: 5
demo-key: 10
To enable authentication on the server, create an API keys file (JSON format) and specify it when starting the server:

```json
[
{ "key": "key1", "limit": 100 },
{ "key": "test-token", "limit": 5 },
{ "key": "demo-key", "limit": 10 }
]
```

Start the server with authentication:

```bash
$ mmar server --api-keys-file api-keys.yaml
$ mmar server --api-keys-file api-keys.json
```

### Client Usage
Expand All @@ -223,7 +224,7 @@ $ mmar client --local-port 8080 --auth-token key1
You can configure authentication using environment variables:

```bash
export MMAR__API_KEYS_FILE="/path/to/api-keys.yaml"
export MMAR__API_KEYS_FILE="/path/to/api-keys.json"
export MMAR__API_KEY="my-secret-token"
```

Expand Down
33 changes: 27 additions & 6 deletions cmd/mmar/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ func main() {
utils.EnvVarOrDefault(constants.MMAR_ENV_VAR_API_KEYS_FILE, "api-keys.json"),
constants.SERVER_API_KEYS_FILE_HELP,
)
serverMaxTunnelsPerIP := serverCmd.Int(
"max-tunnels-per-ip",
utils.EnvVarOrDefaultInt(constants.MMAR_ENV_VAR_MAX_TUNNELS_PER_IP, constants.MAX_TUNNELS_PER_IP),
constants.SERVER_MAX_TUNNELS_PER_IP_HELP,
)
serverMaxRequestSize := serverCmd.Int(
"max-request-size",
utils.EnvVarOrDefaultInt(constants.MMAR_ENV_VAR_MAX_REQUEST_SIZE, constants.MAX_REQ_BODY_SIZE),
constants.SERVER_MAX_REQUEST_SIZE_HELP,
)

clientCmd := flag.NewFlagSet(constants.CLIENT_CMD, flag.ExitOnError)
clientLocalPort := clientCmd.String(
Expand Down Expand Up @@ -83,15 +93,23 @@ func main() {

switch os.Args[1] {
case constants.SERVER_CMD:
serverCmd.Parse(os.Args[2:])
if err := serverCmd.Parse(os.Args[2:]); err != nil {
fmt.Fprintf(os.Stderr, "Error parsing server command flags: %v\n", err)
os.Exit(1)
}
mmarServerConfig := server.ConfigOptions{
HttpPort: *serverHttpPort,
TcpPort: *serverTcpPort,
ApiKeysFile: *serverApiKeysFile,
HttpPort: *serverHttpPort,
TcpPort: *serverTcpPort,
ApiKeysFile: *serverApiKeysFile,
MaxTunnelsPerIP: *serverMaxTunnelsPerIP,
MaxRequestSize: *serverMaxRequestSize,
}
server.Run(mmarServerConfig)
case constants.CLIENT_CMD:
clientCmd.Parse(os.Args[2:])
if err := clientCmd.Parse(os.Args[2:]); err != nil {
fmt.Fprintf(os.Stderr, "Error parsing client command flags: %v\n", err)
os.Exit(1)
}
mmarClientConfig := client.ConfigOptions{
LocalPort: *clientLocalPort,
TunnelHttpPort: *clientTunnelHttpPort,
Expand All @@ -104,7 +122,10 @@ func main() {
}
client.Run(mmarClientConfig)
case constants.VERSION_CMD:
versionCmd.Parse(os.Args[2:])
if err := versionCmd.Parse(os.Args[2:]); err != nil {
fmt.Fprintf(os.Stderr, "Error parsing version command flags: %v\n", err)
os.Exit(1)
}
fmt.Println("mmar version", constants.MMAR_VERSION)
default:
utils.MmarUsage()
Expand Down
44 changes: 23 additions & 21 deletions constants/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,27 @@ const (
TUNNEL_HOST = "mmar.dev"
TUNNEL_HTTP_PORT = "443"

MMAR_ENV_VAR_SERVER_HTTP_PORT = "MMAR__SERVER_HTTP_PORT"
MMAR_ENV_VAR_SERVER_TCP_PORT = "MMAR__SERVER_TCP_PORT"
MMAR_ENV_VAR_LOCAL_PORT = "MMAR__LOCAL_PORT"
MMAR_ENV_VAR_TUNNEL_HTTP_PORT = "MMAR__TUNNEL_HTTP_PORT"
MMAR_ENV_VAR_TUNNEL_TCP_PORT = "MMAR__TUNNEL_TCP_PORT"
MMAR_ENV_VAR_TUNNEL_HOST = "MMAR__TUNNEL_HOST"
MMAR_ENV_VAR_CUSTOM_DNS = "MMAR__CUSTOM_DNS"
MMAR_ENV_VAR_CUSTOM_CERT = "MMAR__CUSTOM_CERT"
MMAR_ENV_VAR_CUSTOM_NAME = "MMAR__CUSTOM_NAME"
MMAR_ENV_VAR_API_KEY = "MMAR__API_KEY"
MMAR_ENV_VAR_API_KEYS_FILE = "MMAR__API_KEYS_FILE"
MMAR_ENV_VAR_SERVER_HTTP_PORT = "MMAR__SERVER_HTTP_PORT"
MMAR_ENV_VAR_SERVER_TCP_PORT = "MMAR__SERVER_TCP_PORT"
MMAR_ENV_VAR_LOCAL_PORT = "MMAR__LOCAL_PORT"
MMAR_ENV_VAR_TUNNEL_HTTP_PORT = "MMAR__TUNNEL_HTTP_PORT"
MMAR_ENV_VAR_TUNNEL_TCP_PORT = "MMAR__TUNNEL_TCP_PORT"
MMAR_ENV_VAR_TUNNEL_HOST = "MMAR__TUNNEL_HOST"
MMAR_ENV_VAR_CUSTOM_DNS = "MMAR__CUSTOM_DNS"
MMAR_ENV_VAR_CUSTOM_CERT = "MMAR__CUSTOM_CERT"
MMAR_ENV_VAR_CUSTOM_NAME = "MMAR__CUSTOM_NAME"
MMAR_ENV_VAR_API_KEY = "MMAR__API_KEY"
MMAR_ENV_VAR_API_KEYS_FILE = "MMAR__API_KEYS_FILE"
MMAR_ENV_VAR_MAX_TUNNELS_PER_IP = "MMAR__SERVER_MAX_TUNNELS_PER_IP"
MMAR_ENV_VAR_MAX_REQUEST_SIZE = "MMAR__SERVER_MAX_REQUEST_SIZE"

SERVER_STATS_DEFAULT_USERNAME = "admin"
SERVER_STATS_DEFAULT_PASSWORD = "admin"

SERVER_HTTP_PORT_HELP = "Define port where mmar will bind to and run on server for HTTP requests."
SERVER_TCP_PORT_HELP = "Define port where mmar will bind to and run on server for TCP connections."
SERVER_HTTP_PORT_HELP = "Define port where mmar will bind to and run on server for HTTP requests."
SERVER_TCP_PORT_HELP = "Define port where mmar will bind to and run on server for TCP connections."
SERVER_MAX_TUNNELS_PER_IP_HELP = "Define maximum number of tunnels allowed per IP address."
SERVER_MAX_REQUEST_SIZE_HELP = "Define maximum request body size in bytes."

CLIENT_LOCAL_PORT_HELP = "Define the port where your local dev server is running to expose through mmar."
CLIENT_HTTP_PORT_HELP = "Define port of mmar HTTP server to make requests through the tunnel."
Expand All @@ -47,7 +51,7 @@ const (

MAX_TUNNELS_PER_IP = 5
TUNNEL_RECONNECT_TIMEOUT = 3
GRACEFUL_SHUTDOWN_TIMEOUT = 3
GRACEFUL_SHUTDOWN_TIMEOUT = 1
TUNNEL_CREATE_TIMEOUT = 3
REQ_BODY_READ_CHUNK_TIMEOUT = 3
DEST_REQUEST_TIMEOUT = 30
Expand Down Expand Up @@ -81,10 +85,8 @@ const (
RESET = "\033[0m"
)

var (
MMAR_SUBCOMMANDS = [][]string{
{"server", "Runs a mmar server. Run this on your publicly reachable server if you're self-hosting mmar."},
{"client", "Runs a mmar client. Run this on your machine to expose your localhost on a public URL."},
{"version", "Prints the installed version of mmar."},
}
)
var MMAR_SUBCOMMANDS = [][]string{
{"server", "Runs a mmar server. Run this on your publicly reachable server if you're self-hosting mmar."},
{"client", "Runs a mmar client. Run this on your machine to expose your localhost on a public URL."},
{"version", "Prints the installed version of mmar."},
}
Loading