Skip to content
Snippets Groups Projects
utils.go 2.25 KiB
Newer Older
  • Learn to ignore specific revisions
  • Konrad Zemek's avatar
    Konrad Zemek committed
    // Copyright 2019 Path Network, Inc. All rights reserved.
    // Use of this source code is governed by a BSD-style
    // license that can be found in the LICENSE file.
    
    package main
    
    import (
    	"fmt"
    	"net"
    	"syscall"
    )
    
    type Protocol int
    
    const (
    	TCP Protocol = iota
    	UDP
    )
    
    func CheckOriginAllowed(remoteIP net.IP) bool {
    	if len(Opts.AllowedSubnets) == 0 {
    		return true
    	}
    
    	for _, ipNet := range Opts.AllowedSubnets {
    		if ipNet.Contains(remoteIP) {
    			return true
    		}
    	}
    	return false
    }
    
    func DialUpstreamControl(sport int) func(string, string, syscall.RawConn) error {
    	return func(network, address string, c syscall.RawConn) error {
    		var syscallErr error
    		err := c.Control(func(fd uintptr) {
    			if Opts.Protocol == "tcp" {
    				syscallErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_SYNCNT, 2)
    				if syscallErr != nil {
    
    					syscallErr = fmt.Errorf("setsockopt(IPPROTO_TCP, TCP_SYNCTNT, 2): %w", syscallErr)
    
    Konrad Zemek's avatar
    Konrad Zemek committed
    					return
    				}
    			}
    
    			syscallErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, syscall.IP_TRANSPARENT, 1)
    			if syscallErr != nil {
    
    				syscallErr = fmt.Errorf("setsockopt(IPPROTO_IP, IP_TRANSPARENT, 1): %w", syscallErr)
    
    Konrad Zemek's avatar
    Konrad Zemek committed
    				return
    			}
    
    			syscallErr = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
    			if syscallErr != nil {
    
    				syscallErr = fmt.Errorf("setsockopt(SOL_SOCKET, SO_REUSEADDR, 1): %w", syscallErr)
    
    Konrad Zemek's avatar
    Konrad Zemek committed
    				return
    			}
    
    			if sport == 0 {
    				ipBindAddressNoPort := 24
    
    				syscallErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, ipBindAddressNoPort, 1)
    				if syscallErr != nil {
    					syscallErr = fmt.Errorf("setsockopt(SOL_SOCKET, IPPROTO_IP, %d): %w", Opts.Mark, syscallErr)
    					return
    				}
    
    Konrad Zemek's avatar
    Konrad Zemek committed
    			}
    
    			if Opts.Mark != 0 {
    				syscallErr = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, Opts.Mark)
    				if syscallErr != nil {
    
    					syscallErr = fmt.Errorf("setsockopt(SOL_SOCK, SO_MARK, %d): %w", Opts.Mark, syscallErr)
    
    Konrad Zemek's avatar
    Konrad Zemek committed
    					return
    				}
    			}
    
    			if network == "tcp6" || network == "udp6" {
    
    				syscallErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0)
    
    Konrad Zemek's avatar
    Konrad Zemek committed
    				if syscallErr != nil {
    
    					syscallErr = fmt.Errorf("setsockopt(IPPROTO_IP, IPV6_ONLY, 0): %w", syscallErr)
    
    Konrad Zemek's avatar
    Konrad Zemek committed
    					return
    				}
    			}
    		})
    
    		if err != nil {
    			return err
    		}
    		return syscallErr
    	}
    }