commit
ef74b1c529
@ -0,0 +1,33 @@ |
||||
# Regela ARP proxy |
||||
|
||||
### Very simple, lazy method to configure arp tables |
||||
#### Written for our Virtuozzo's Community OS servers by Elizar [@Regela](https://sources.krechet.tech/Regela) |
||||
|
||||
#### Include example config file in .yml, where is: |
||||
- name: *interfacename* |
||||
- addresses: *list of ips on interfacename* |
||||
|
||||
#### Usage: move config.yum in folder /etc/RegelaArpProxy/ and run binary |
||||
|
||||
``` |
||||
~# RegelaArpProxy --help |
||||
Usage of RegelaArpProxy: |
||||
-example |
||||
-i string |
||||
Config File (default "/etc/RegelaArpProxy/config.yml") |
||||
|
||||
~# RegelaArpProxy -example |
||||
interfaces: |
||||
- name: br0 |
||||
addresses: |
||||
- 10.10.100.10 |
||||
- 10.10.100.11 |
||||
- 10.10.100.12 |
||||
- 10.10.100.13 |
||||
- name: br1 |
||||
addresses: |
||||
- 10.10.101.10 |
||||
- 10.10.101.11 |
||||
- 10.10.101.12 |
||||
- 10.10.101.13 |
||||
``` |
@ -0,0 +1,8 @@ |
||||
interfaces: |
||||
- name: vlan101 |
||||
addresses: |
||||
- 10.10.3.2 |
||||
- 10.10.3.5 |
||||
- name: vlan102 |
||||
addresses: |
||||
- 10.10.116.11 |
@ -0,0 +1,135 @@ |
||||
package main |
||||
|
||||
import ( |
||||
"bytes" |
||||
"flag" |
||||
"fmt" |
||||
"github.com/goccy/go-yaml" |
||||
"github.com/mdlayher/arp" |
||||
"github.com/mdlayher/ethernet" |
||||
"io" |
||||
"io/ioutil" |
||||
"log" |
||||
"net" |
||||
"os" |
||||
"time" |
||||
) |
||||
|
||||
type Interface struct{ |
||||
Name string |
||||
Addresses []net.IP |
||||
} |
||||
|
||||
type Settings struct { |
||||
Interfaces []Interface |
||||
} |
||||
|
||||
|
||||
var ( |
||||
configFile = flag.String("i", "/etc/RegelaArpProxy/config.yml", "Config File") |
||||
printExampleFlag = flag.Bool("example",false,"") |
||||
|
||||
|
||||
) |
||||
|
||||
func task(iface Interface){ |
||||
ifi, err := net.InterfaceByName(iface.Name) |
||||
if err != nil { |
||||
log.Fatal(err) |
||||
} |
||||
|
||||
client, err := arp.Dial(ifi) |
||||
if err != nil { |
||||
log.Fatalf("couldn't create ARP client: %s", err) |
||||
} |
||||
|
||||
// Handle ARP requests bound for designated IPv4 address, using proxy ARP
|
||||
// to indicate that the address belongs to this machine
|
||||
for { |
||||
pkt, eth, err := client.Read() |
||||
if err != nil { |
||||
if err == io.EOF { |
||||
log.Println("EOF") |
||||
break |
||||
} |
||||
log.Fatalf("error processing ARP requests: %s", err) |
||||
} |
||||
|
||||
// Ignore ARP replies
|
||||
if pkt.Operation != arp.OperationRequest { |
||||
continue |
||||
} |
||||
|
||||
// Ignore ARP requests which are not broadcast or bound directly for
|
||||
// this machine
|
||||
if !bytes.Equal(eth.Destination, ethernet.Broadcast) /*&& !bytes.Equal(eth.Destination, ifi.HardwareAddr)*/ { |
||||
continue |
||||
} |
||||
|
||||
log.Printf("request: who-has %s? tell %s (%s)", pkt.TargetIP, pkt.SenderIP, pkt.SenderHardwareAddr) |
||||
|
||||
// Ignore ARP requests which do not indicate the target IP
|
||||
for _, ip := range iface.Addresses { |
||||
if pkt.TargetIP.Equal(ip) { |
||||
log.Printf(" reply: %s is-at %s", ip, ifi.HardwareAddr) |
||||
if err := client.Reply(pkt, ifi.HardwareAddr, ip); err != nil { |
||||
log.Fatal(err) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
func printExample() { |
||||
settings := Settings{ |
||||
Interfaces: []Interface{ |
||||
{ |
||||
Name: "br0", |
||||
Addresses: []net.IP{ |
||||
net.ParseIP("10.10.100.10"), |
||||
net.ParseIP("10.10.100.11"), |
||||
net.ParseIP("10.10.100.12"), |
||||
net.ParseIP("10.10.100.13"), |
||||
}, |
||||
}, |
||||
{ |
||||
Name: "br1", |
||||
Addresses: []net.IP{ |
||||
net.ParseIP("10.10.101.10"), |
||||
net.ParseIP("10.10.101.11"), |
||||
net.ParseIP("10.10.101.12"), |
||||
net.ParseIP("10.10.101.13"), |
||||
}, |
||||
}, |
||||
}, |
||||
} |
||||
out, _ := yaml.Marshal(settings) |
||||
fmt.Printf("%s",out) |
||||
} |
||||
|
||||
func main() { |
||||
flag.Parse() |
||||
|
||||
if *printExampleFlag{ |
||||
printExample() |
||||
os.Exit(0) |
||||
} |
||||
|
||||
cf, err := ioutil.ReadFile(*configFile) |
||||
if err != nil { |
||||
log.Fatalf("Read configuration error: %s", err.Error()) |
||||
} |
||||
|
||||
settings := Settings{} |
||||
err = yaml.Unmarshal(cf,&settings) |
||||
for _, iface := range settings.Interfaces { |
||||
go task(iface) |
||||
} |
||||
for { |
||||
time.Sleep(time.Hour) |
||||
} |
||||
|
||||
// Ensure valid interface and IPv4 address
|
||||
|
||||
} |
Loading…
Reference in new issue