get remote MAC address from SESSION

Post your questions about SoftEther VPN software here. Please answer questions if you can afford.
Post Reply
Posts: 6
Joined: Sun Apr 15, 2018 10:25 am

get remote MAC address from SESSION

Post by top-master » Mon Apr 16, 2018 3:59 am

I did write a packet adapter nothing new just based on the existing
"PACKET_ADAPTER" struct source which's method does get called and resave
the "SESSION" struct pointer so far so good but my question is that:
once we do connect to an SE server we need it's MAC address in
packet-adapter to be able to create L2 packets and send to the SE server
but where is that MAC address?

where ever that MAC address is please inform me too.
below is the session structure which you all may know:

// Session structure
struct SESSION
LOCK *lock; // Lock
REF *ref; // Reference counter
CEDAR *Cedar; // Cedar
BOOL LocalHostSession; // Local host session
BOOL ServerMode; // Server mode session
BOOL NormalClient; // Connecting session from a regular client (not
such as localbridge)
BOOL LinkModeClient; // Link mode client
BOOL LinkModeServer; // Link mode server
BOOL SecureNATMode; // SecureNAT session
BOOL BridgeMode; // Bridge session
BOOL BridgeIsEthLoopbackBlock; // Loopback is disabled on the Ethernet
BOOL VirtualHost; // Virtual host mode
BOOL L3SwitchMode; // Layer-3 switch mode
BOOL InProcMode; // In-process mode
THREAD *Thread; // Management thread
CONNECTION *Connection; // Connection
char ClientIP[64]; // Client IP
CLIENT_OPTION *ClientOption; // Client connection options
CLIENT_AUTH *ClientAuth; // Client authentication data
volatile BOOL Halt; // Halting flag
volatile BOOL CancelConnect; // Cancel the connection
EVENT *HaltEvent; // Halting event
UINT Err; // Error value
HUB *Hub; // HUB
CANCEL *Cancel1; // Cancel object 1
CANCEL *Cancel2; // Cancel object 2
PACKET_ADAPTER *PacketAdapter; // Packet adapter
UCHAR UdpSendKey[16]; // UDP encryption key for transmission
UCHAR UdpRecvKey[16]; // UDP encryption key for reception
UINT ClientStatus; // Client Status
BOOL RetryFlag; // Retry flag (client)
BOOL ForceStopFlag; // Forced stop flag (client)
UINT CurrentRetryCount; // Current retry counter (client)
UINT RetryInterval; // Retry interval (client)
BOOL ConnectSucceed; // Connection success flag (client)
BOOL SessionTimeOuted; // Session times out
UINT Timeout; // Time-out period
UINT64 NextConnectionTime; // Time to put next additional connection
IP ServerIP; // IP address of the server
BOOL ClientModeAndUseVLan; // Use a virtual LAN card in client mode
BOOL UseSSLDataEncryption; // Use SSL data encryption
LOCK *TrafficLock; // Traffic data lock
LINK *Link; // A reference to the link object
SNAT *SecureNAT; // A reference to the SecureNAT object
BRIDGE *Bridge; // A reference to the Bridge object
NODE_INFO NodeInfo; // Node information
UINT64 LastIncrementTraffic; // Last time that updated the traffic data of
the user
BOOL AdministratorMode; // Administrator mode
LIST *CancelList; // Cancellation list
L3IF *L3If; // Layer-3 interface
IP DefaultDns; // IP address of the default DNS server
BOOL IPv6Session; // IPv6 session (Physical communication is IPv6)
UINT UniqueId; // Unique ID
UCHAR IpcMacAddress[6]; // MAC address for IPC
UCHAR Padding[2];

IP ServerIP_CacheForNextConnect; // Server IP, cached for next connect

UINT64 CreatedTime; // Creation date and time
UINT64 LastCommTime; // Last communication date and time
UINT64 LastCommTimeForDormant; // Last communication date and time (for
TRAFFIC *Traffic; // Traffic data
TRAFFIC *OldTraffic; // Old traffic data
UINT64 TotalSendSize; // Total transmitted data size
UINT64 TotalRecvSize; // Total received data size
UINT64 TotalSendSizeReal; // Total transmitted data size (no compression)
UINT64 TotalRecvSizeReal; // Total received data size (no compression)
char *Name; // Session name
char *Username; // User name
char UserNameReal[MAX_USERNAME_LEN + 1]; // User name (real)
char GroupName[MAX_USERNAME_LEN + 1]; // Group name
POLICY *Policy; // Policy
UCHAR SessionKey[SHA1_SIZE]; // Session key
UINT SessionKey32; // 32bit session key
char SessionKeyStr[64]; // Session key string
UINT MaxConnection; // Maximum number of concurrent TCP connections
BOOL UseEncrypt; // Use encrypted communication
BOOL UseFastRC4; // Use high speed RC4 encryption
BOOL UseCompress; // Use data compression
BOOL HalfConnection; // Half connection mode
BOOL QoS; // VoIP / QoS
BOOL NoSendSignature; // Do not send a signature
BOOL IsOpenVPNL3Session; // Whether OpenVPN L3 session
BOOL IsOpenVPNL2Session; // Whether OpenVPN L2 session
UINT NumDisconnected; // Number of socket disconnection
BOOL NoReconnectToSession; // Disable to reconnect to the session
char UnderlayProtocol[64]; // Physical communication protocol
UINT64 FirstConnectionEstablisiedTime; // Connection completion time of
the first connection
UINT64 CurrentConnectionEstablishTime; // Completion time of this
UINT NumConnectionsEatablished; // Number of connections established so
UINT AdjustMss; // MSS adjustment value
BOOL IsVPNClientAndVLAN_Win32; // Is the VPN Client session with a VLAN
card (Win32)

BOOL IsRUDPSession; // Whether R-UDP session
UINT RUdpMss; // The value of the MSS should be applied while the
R-UDP is used
BOOL EnableBulkOnRUDP; // Allow the bulk transfer in the R-UDP session
BOOL EnableHMacOnBulkOfRUDP; // Use the HMAC to sign the bulk transfer of
R-UDP session
BOOL EnableUdpRecovery; // Enable the R-UDP recovery

BOOL UseUdpAcceleration; // Use of UDP acceleration mode
BOOL UseHMacOnUdpAcceleration; // Use the HMAC in the UDP acceleration
UDP_ACCEL *UdpAccel; // UDP acceleration
BOOL IsUsingUdpAcceleration; // Flag of whether the UDP acceleration is
UINT UdpAccelMss; // MSS value to be applied while the UDP acceleration
is used
BOOL UdpAccelFastDisconnectDetect; // Fast disconnection detection is

BOOL IsAzureSession; // Whether the session via VPN Azure
IP AzureRealServerGlobalIp; // Real global IP of the server-side in the
case of session via VPN Azure

ACCOUNT *Account; // Client account
UINT VLanDeviceErrorCount; // Number of times that the error occurred in
the virtual LAN card
BOOL Win32HideConnectWindow; // Hide the status window
BOOL Win32HideNicInfoWindow; // Hide the NIC information window
BOOL UserCanceled; // Canceled by the user
UINT64 LastTryAddConnectTime; // Last time that attempted to add a

BOOL IsMonitorMode; // Whether the monitor mode
BOOL IsBridgeMode; // Whether the bridge mode
BOOL UseClientLicense; // Number of assigned client licenses
BOOL UseBridgeLicense; // Number of assigned bridge licenses

COUNTER *LoggingRecordCount; // Counter for the number of logging records

BOOL FreeInfoShowed; // Whether a warning about Free Edition has already

BOOL Client_NoSavePassword; // Prohibit the password saving
wchar_t *Client_Message; // Message that has been sent from the server

LIST *DelayedPacketList; // Delayed packet list
UINT Flag1;

USER *NumLoginIncrementUserObject; // User objects to increment the nymber
of logins
HUB *NumLoginIncrementHubObject; // Virtual HUB object to increment the
number of logins
UINT64 NumLoginIncrementTick; // Time to perform increment a number of

BOOL FirstTimeHttpRedirect; // Redirect HTTP only for the first time
char FirstTimeHttpRedirectUrl[128]; // URL for redirection only the first
UINT FirstTimeHttpAccessCheckIp; // IP address for access checking

// To examine the maximum number of alowed logging target packets per
UINT64 MaxLoggedPacketsPerMinuteStartTick; // Inspection start time
UINT CurrentNumPackets; // Current number of packets

// Measures for D-Link bug
UINT64 LastDLinkSTPPacketSendTick; // Last D-Link STP packet transmission
UCHAR LastDLinkSTPPacketDataHash[MD5_SIZE]; // Last D-Link STP packet hash

Posts: 2458
Joined: Mon Feb 24, 2014 11:03 am

Re: get remote MAC address from SESSION

Post by thisjun » Wed May 16, 2018 8:14 am

Packet adapter doesn't have MAC address because packet adapter is like as port of switching hub of real network.

Posts: 6
Joined: Sun Apr 15, 2018 10:25 am

Re: get remote MAC address from SESSION

Post by top-master » Thu May 31, 2018 5:06 am

there was no such thing as "mac address" in session struct at the end
but have fixed my issue by adding a DHCP client to the packet adapter

I had this issue because Android does not provide permission/access to Layer2/Tap network adapter/interface
so I have written my own virtual Tap device after that have expected all to work but that was not the case first have asked here from the professionals then later wrote and added the DHCP client to the mentioned packet adapter which gets:
"mac address". "allocated IP address" and ... from the SE server

Posts: 19
Joined: Mon Jun 10, 2019 7:17 am

Re: get remote MAC address from SESSION

Post by coolname » Tue Jun 18, 2019 10:39 pm

I'm trying to build an android client app for softether but ran into the issue that Android only supports a "tun" while softether expects a "tap."

Where did you build your virtual "tap" device, on the server side or android client side? I'm assuming it's on the server side.

I'm at the point of trying to put together such a Tap and Tun conversion on the server side and am looking into the interop_OpenVpn module. I'm thinking about replicating the ovs module logic to initiate IPC/Tube so that ARP can be used to get a mac address of the client, and eventually a mac header added to the tun ip packets and sent out of the door. I'm expecting the incoming data flow (from outside server to softether and then the client) to work as is w/o having to make any code changes to the server, but not certain if that's the case.

Does the above idea look right to you? I'd appreciate very much if you could kindly share your experience with the virtual Tap device PA.


Posts: 6
Joined: Sun Apr 15, 2018 10:25 am

Re: get remote MAC address from SESSION

Post by top-master » Wed Jun 19, 2019 12:20 pm

In our case, we tried to prevent any change to the SE-Server side codes because:
  • We did not want to slow down the server (although it might have worked, it's supposed to be a super-computer after all).
  • And We did not want to lose the ability to update, I mean, else my client would need to pay a developer each time (to merge the codes with the latest SE-update).
So, emulating a Layer2/TAP device on the user-side was our choice and in the end, it worked quite well (Never underestimate native codes speed).

Although the mentioned project was developed under the "Apache 2.0" license, the client decided to keep it closed source (at least for now), and I am not allowed to share anything with you;
But still, I can tell you that:
  • Your idea might work out, but I do prefer our approach (which is putting the overhead on each mobile instead of grouping it on the server).
  • If you change the server but the client does not respond to any packet then your time was wasted, so, better change the client and not the other way around.
  • Once you are convinced to create a client, use DHCP instead of ARP to get informations from the SE-Server (In my experience the server will never answer any ARP-Packet, but may send you some which you do not need to answer)
  • As you might know, the difference between a Layer2-packet with a Layer3-packet is that the "MAC_HEADER" is removed from the beginning of the Layer3-packet which Android provides, so, you will need to prepend it again there with valid data, so that the SE-codes can handle it, which is an advanced topic (I mean, prepending is easy, but "valid data" is what is meant by emulating)
  • In fact I think that adding support for DHCP and ARP is simpler than emulating the "MAC_HEADER" of Layer2.
Mac-Header example (from SoftEtherVPN/src/Mayaqua/TcpIp.h):

Code: Select all

// ...

#ifdef	OS_WIN32
#pragma pack(push, 1)
#endif	// OS_WIN32

	UCHAR	DestAddress[6]; // Source MAC address
	UCHAR	SrcAddress[6]; // Destination MAC address
	USHORT	Protocol; // Protocol

// ...

#ifdef	OS_WIN32
#pragma pack(pop)
#endif	// OS_WIN32
I hope this tip helps, but I might not be able to answer again...

Posts: 19
Joined: Mon Jun 10, 2019 7:17 am

Re: get remote MAC address from SESSION

Post by coolname » Wed Jun 19, 2019 11:51 pm

Thank you so much for the response! This is very encouraging. I'm so glad to hear that you made it work with android side native code, w/o having to touch the server code which is the ideal solution!

I've tried to do the Tap/Tun translation on the client side but ran into these issues:

1. App couldn't get android Mac
Android tun interface out of VpnService's establish() doesn't allow me to get hold of the tun's Mac address. As a result, my android VPN app can't even get its own Mac address. I chose to hardcode the Mac and added the Mac header to the IP packets right before they are sent to server. Server did get them. But the only responses received from server were ARP requests. The app did respond to the ARP meant for itself, and ignored the others. There were no other responses from server. As a result the android device couldn't connect to internet while the app is connected to the softether server. I believe this is because the ARP mapping between IP & Mac was not properly established on server side.

2. App doesn't have access to L2/L3 on android
Android doesn't allow the app to do raw socket operations on the SSL connection to the server and all the app gets is IP packets from the tun. As a result sending ARP or DHCP broadcasts through L2/Tap is not possible. The only exception I believe is rooted phones but our target is ordinary phones, not rooted ones. I believe wrapping such packets such as DHCP inside of softether blocks is possible but I thought I have to have a tun before requesting for DHCP IP, but to get a tun android establish() requires a local VPN IP (supposedly from DHCP) before the tun is even created. Hence the chicken and egg issue. I believe I'm missing something here.

So I turned to the server side. But I'm so glad to know that you were able to get Tap, DHCP, and Mac header all handled on the client side. This is the ideal the solution! Great job!

W/o going into the specifics of your project, I wonder if you could help shed some light on the above 2 android specific issues. Are there any resources online that you could point me to understand how to do DHCP/Tap on android? BTW, have you looked into iOS as well? Do you think the same idea of only changing client code would work for iOS platform as well?

Looking forward to your reply. Feel free to email me at

Posts: 19
Joined: Mon Jun 10, 2019 7:17 am

Re: get remote MAC address from SESSION

Post by coolname » Sat Jun 22, 2019 5:06 pm

Thanks to your tip, I was able to make DHCP work with a hardcoded Mac address! I will generate a random Mac later.

I understand an L2 Ethernet frame can be assembled as Mac header + L3 IP Packet + CRC32. So for outgoing packets to server I added the mac header and tailing CRC to the IP packets read from tun and sent to server. For incoming packets from server, I discard others and only forward IPv4 L2 ethernet packets and strip the mac header & trailing CRC32 and forward the remaining IP packets to android tun. The Mac header I prepend is this:

Dest Mac: softether server Mac - hardcoded - will figure out a way to get it from server later perhaps from ARP requests.
Source Mac: android Mac - hardcoded
EtherType/Protocol:0x800 for IPv4

But I'm not seeing anything new from server other than repeated ARP as before. Client's responses to ARP requests meant for the client don't seem to stop the repeated incoming ARP requests.

I guess the issue might be the generated L2 ethernet frames are incorrect, and they are discarded down the line on the server side. I'll be tweaking the CRC to see if it's wrong, perhaps through Endian32(Swap32(crc)).

Does softether server code validate the CRC so I could debug into it and check whether or not the CRC is correct? Or is it checked out side of softether and if so what would be the way to know if the CRC is correct? Do you see issues with the above approach?

I would appreciate any tip to move forward. I'm stuck. Going back to modifying the server would not be the right choice.

Thank you!

Posts: 19
Joined: Mon Jun 10, 2019 7:17 am

Re: get remote MAC address from SESSION

Post by coolname » Sun Jun 23, 2019 12:27 am

Update: the client now receives IPv4 packets including DNS response(non-exist domain), and some other packets from a few Google IP's. Still no internet connection though.

Should I open up the ip packets and tweak them before sending or after receiving in order for it to work? The CRC didn't seem to make any difference. The result seems to be the same with or w/o the added CRC.

Again I would appreciate any tip at this point. Thank you!

Site Admin
Posts: 1468
Joined: Sat Mar 09, 2013 5:37 am

Re: get remote MAC address from SESSION

Post by cedar » Tue Jul 09, 2019 5:58 am

Have you tried packet capture on the VPN server side?

Posts: 19
Joined: Mon Jun 10, 2019 7:17 am

Re: get remote MAC address from SESSION

Post by coolname » Sun Jul 14, 2019 4:07 am

Thanks for your response. The issue has been fixed. I was able to move forward but ran into new issues on UDP acceleration. Please see this post for details:

Post Reply