diff --git a/cover.html b/cover.html
new file mode 100644
index 0000000..f532d20
--- /dev/null
+++ b/cover.html
@@ -0,0 +1,108 @@
+
+
+
+
+
+ Go Coverage Report
+
+
+
+
+
+
+
+
+ not tracked
+
+ no coverage
+ low coverage
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ high coverage
+
+
+
+
+
+
+
+
+
diff --git a/cover.out b/cover.out
new file mode 100644
index 0000000..79b28a0
--- /dev/null
+++ b/cover.out
@@ -0,0 +1 @@
+mode: atomic
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..3953084
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,3 @@
+module github.com/gopatchy/proxy
+
+go 1.20
diff --git a/justfile b/justfile
new file mode 100644
index 0000000..a22d1ac
--- /dev/null
+++ b/justfile
@@ -0,0 +1,18 @@
+go := env_var_or_default('GOCMD', 'go')
+
+default: tidy test
+
+tidy:
+ {{go}} mod tidy
+ goimports -l -w .
+ gofumpt -l -w .
+ {{go}} fmt
+
+test:
+ {{go}} vet
+ golangci-lint run .
+ {{go}} test -race -coverprofile=cover.out -timeout=60s
+ {{go}} tool cover -html=cover.out -o=cover.html
+
+todo:
+ -git grep -e TODO --and --not -e ignoretodo
diff --git a/proxy.go b/proxy.go
new file mode 100644
index 0000000..c51d237
--- /dev/null
+++ b/proxy.go
@@ -0,0 +1,40 @@
+package proxy
+
+import "net"
+
+type Proxy struct {
+ backend *net.TCPAddr
+ listener *net.TCPListener
+}
+
+func NewProxy(backend *net.TCPAddr) (*Proxy, error) {
+ var err error
+
+ p := &Proxy{
+ backend: backend,
+ }
+
+ p.listener, err = net.ListenTCP("tcp", nil)
+ if err != nil {
+ return nil, err
+ }
+
+ go p.accept()
+
+ return p, nil
+}
+
+func (p *Proxy) Close() {
+ p.listener.Close()
+}
+
+func (p *Proxy) accept() {
+ for {
+ conn, err := p.listener.Accept()
+ if err != nil {
+ return
+ }
+
+ conn.Close()
+ }
+}